go語言實(shí)現(xiàn)同步操作項目示例
1. 簡介
本文探討了并發(fā)編程中的同步操作,講述了為何需要同步以及兩種常見的實(shí)現(xiàn)方式:sync.Cond和通道。通過比較它們的適用場景,讀者可以更好地了解何時選擇使用不同的同步方式。本文旨在幫助讀者理解同步操作的重要性以及選擇合適的同步機(jī)制來確保多個協(xié)程之間的正確協(xié)調(diào)和數(shù)據(jù)共享的一致性。
2. 為什么需要同步操作
2.1 為什么需要同步操作
這里舉一個簡單的圖像處理場景來說明。任務(wù)A負(fù)責(zé)加載圖像,任務(wù)B負(fù)責(zé)對已加載的圖像進(jìn)行處理。這兩個任務(wù)將在兩個并發(fā)協(xié)程中同時啟動,實(shí)現(xiàn)并行執(zhí)行。然而,這兩個任務(wù)之間存在一種依賴關(guān)系:只有當(dāng)圖像加載完成后,任務(wù)B才能安全地執(zhí)行圖像處理操作。
在這種情況下,我們需要對這兩個任務(wù)進(jìn)行協(xié)調(diào)和同步。任務(wù)B需要確保在處理已加載的圖像之前,任務(wù)A已經(jīng)完成了圖像加載操作。通過使用適當(dāng)?shù)耐綑C(jī)制來確保任務(wù)B在圖像準(zhǔn)備就緒后再進(jìn)行處理,從而避免數(shù)據(jù)不一致性和并發(fā)訪問錯誤的問題。
事實(shí)上,在我們的開發(fā)過程中,經(jīng)常會遇到這種需要同步的場景,所以了解同步操作的實(shí)現(xiàn)方式是必不可少的,下面我們來仔細(xì)介紹。
2.2 如何實(shí)現(xiàn)同步操作呢
通過上面的例子,我們知道當(dāng)多協(xié)程任務(wù)存在依賴關(guān)系時,同步操作是必不可免的,那如何實(shí)現(xiàn)同步操作呢?這里的一個簡單想法,便是采用一個簡單的條件變量,不斷采用輪詢的方式來檢查事件是否已經(jīng)發(fā)生或條件是否滿足,此時便可實(shí)現(xiàn)簡單的同步操作。代碼示例如下:
package main import ( ? ? ? ? "fmt" ? ? ? ? "time" ) var condition bool func waitForCondition() { ? ? ? ?for !condition { ? ? ? ? ? ? ?// 輪詢條件是否滿足 ? ? ? ? ? ? ?time.Sleep(time.Millisecond * 100) ? ? ? ?} ? ? ? ?fmt.Println("Condition is satisfied") } func main() { ? ? ? ? go waitForCondition() ? ? ? ? time.Sleep(time.Second) ? ? ? ? condition = true // 修改條件 ? ? ? ? time.Sleep(time.Second) }
在上述代碼中,waitForCondition 函數(shù)通過輪詢方式檢查條件是否滿足。當(dāng)條件滿足時,才繼續(xù)執(zhí)行下去。
但是這種輪訓(xùn)的方式其實(shí)存在一些缺點(diǎn),首先是資源浪費(fèi),輪詢會消耗大量的 CPU 資源,因為協(xié)程需要不斷地執(zhí)行循環(huán)來檢查條件。這會導(dǎo)致 CPU 使用率升高,浪費(fèi)系統(tǒng)資源,其次是延遲,輪詢方式無法及時響應(yīng)條件的變化。如果條件在循環(huán)的某個時間點(diǎn)滿足,但輪詢檢查的時機(jī)未到,則會延遲對條件的響應(yīng)。最后輪詢方式可能導(dǎo)致協(xié)程的執(zhí)行效率降低。因為協(xié)程需要在循環(huán)中不斷檢查條件,無法進(jìn)行其他有意義的工作。
既然通過輪訓(xùn)一個條件變量來實(shí)現(xiàn)同步操作存在這些問題。那go語言中,是否存在更好的實(shí)現(xiàn)方式,可以避免輪詢方式帶來的問題,提供更高效、及時響應(yīng)的同步機(jī)制。其實(shí)是有的,sync.Cond 和channel便是兩個可以實(shí)現(xiàn)同步操作的原語。
3.實(shí)現(xiàn)方式
3.1 sync.Cond實(shí)現(xiàn)同步操作
使用sync.Cond實(shí)現(xiàn)同步操作的方法,可以參考sync.Cond 這篇文章,也可以按照可以按照以下步驟進(jìn)行:
創(chuàng)建一個條件變量:使用sync.NewCond函數(shù)創(chuàng)建一個sync.Cond類型的條件變量,并傳入一個互斥鎖作為參數(shù)。
在等待條件滿足的代碼塊中使用Wait方法:在需要等待條件滿足的代碼塊中,調(diào)用條件變量的Wait方法,這會使當(dāng)前協(xié)程進(jìn)入等待狀態(tài),并釋放之前獲取的互斥鎖。
在滿足條件的代碼塊中使用Signal或Broadcast方法:在滿足條件的代碼塊中,可以使用Signal方法來喚醒一個等待的協(xié)程,或者使用Broadcast方法來喚醒所有等待的協(xié)程。
下面是一個簡單的例子,演示如何使用sync.Cond實(shí)現(xiàn)同步操作:
package main import ( ? ? ? ? "fmt" ? ? ? ? "sync" ? ? ? ? "time" ) func main() { ? ? ? ? var cond = sync.NewCond(&sync.Mutex{}) ? ? ? ? var ready bool ? ? ? ? // 等待條件滿足的協(xié)程 ? ? ? ? go func() { ? ? ? ? ? ? ? ? fmt.Println("等待條件滿足...") ? ? ? ? ? ? ? ? cond.L.Lock() ? ? ? ? ? ? ? ? for !ready { ? ? ? ? ? ? ? ? ? ? ? ? cond.Wait() ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? fmt.Println("條件已滿足") ? ? ? ? ? ? ? ? cond.L.Unlock() ? ? ? ? }() ? ? ? ? // 模擬一段耗時的操作 ? ? ? ? time.Sleep(time.Second) ? ? ? ? // 改變條件并通知等待的協(xié)程 ? ? ? ? cond.L.Lock() ? ? ? ? ready = true ? ? ? ? cond.Signal() ? ? ? ? cond.L.Unlock() ? ? ? ? // 等待一段時間,以便觀察結(jié)果 ? ? ? ? time.Sleep(time.Second) }
在上面的例子中,我們創(chuàng)建了一個條件變量cond,并定義了一個布爾型變量ready作為條件。在等待條件滿足的協(xié)程中,通過調(diào)用Wait方法等待條件的滿足。在主協(xié)程中,通過改變條件并調(diào)用Signal方法來通知等待的協(xié)程條件已滿足。在等待協(xié)程被喚醒后,輸出"條件已滿足"的消息。
通過使用sync.Cond,我們實(shí)現(xiàn)了一個簡單的同步操作,確保等待的協(xié)程在條件滿足時才會繼續(xù)執(zhí)行。這樣可以避免了不必要的輪詢和資源浪費(fèi),提高了程序的效率。
3.2 channel實(shí)現(xiàn)同步操作
當(dāng)使用通道(channel)實(shí)現(xiàn)同步操作時,可以利用通道的阻塞特性來實(shí)現(xiàn)協(xié)程之間的同步。下面是一個簡單的例子,演示如何使用通道實(shí)現(xiàn)同步操作:
package main import ( ? ? ? ? "fmt" ? ? ? ? "time" ) func main() { ? ? ? ? // 創(chuàng)建一個用于同步的通道 ? ? ? ? done := make(chan bool) ? ? ? ? // 在協(xié)程中執(zhí)行需要同步的操作 ? ? ? ? go func() { ? ? ? ? ? ? ? ? fmt.Println("執(zhí)行一些操作...") ? ? ? ? ? ? ? ? time.Sleep(time.Second) ? ? ? ? ? ? ? ? fmt.Println("操作完成") ? ? ? ? ? ? ? ? // 向通道發(fā)送信號,表示操作已完成 ? ? ? ? ? ? ? ? done <- true ? ? ? ? }() ? ? ? ? fmt.Println("等待操作完成...") ? ? ? ? // 阻塞等待通道接收到信號 ? ? ? ? <-done ? ? ? ? fmt.Println("操作已完成") }
在上面的例子中,我們創(chuàng)建了一個通道done,用于同步操作。在執(zhí)行需要同步的操作的協(xié)程中,首先執(zhí)行一些操作,然后通過向通道發(fā)送數(shù)據(jù)done <- true來表示操作已完成。在主協(xié)程中,我們使用<-done來阻塞等待通道接收到信號,表示操作已完成。
通過使用通道實(shí)現(xiàn)同步操作,我們利用了通道的阻塞特性,確保在操作完成之前,主協(xié)程會一直等待。一旦操作完成并向通道發(fā)送了信號,主協(xié)程才會繼續(xù)執(zhí)行后續(xù)的代碼?;诖藢?shí)現(xiàn)了同步操作。
3.3 實(shí)現(xiàn)方式回顧
從上面的介紹來看,sync.Cond或者channel都可以用來實(shí)現(xiàn)同步操作。
但由于它們是不同的并發(fā)原語,因此在代碼編寫和理解上可能會有一些差異。條件變量是一種在并發(fā)編程中常用的同步機(jī)制,而通道則是一種更通用的并發(fā)原語,可用于實(shí)現(xiàn)更廣泛的通信和同步模式。
在選擇并發(fā)原語時,我們應(yīng)該考慮到代碼的可讀性、可維護(hù)性和性能等因素。有時,使用條件變量可能是更合適和直觀的選擇,而在其他情況下,通道可能更適用。了解不同并發(fā)原語的優(yōu)勢和限制,并根據(jù)具體需求做出適當(dāng)?shù)倪x擇,是編寫高質(zhì)量并發(fā)代碼的關(guān)鍵。
4. channel適用場景說明
事實(shí)上,channel并不是被專門用來實(shí)現(xiàn)同步操作,而是基于channel中阻塞等待的特性,從而來實(shí)現(xiàn)一些簡單的同步操作。雖然sync.Cond是專門設(shè)計來實(shí)現(xiàn)同步操作的,但是在某些場景下,使用通道比使用 sync.Cond更為合適。
其中一個最典型的例子,便是任務(wù)的有序執(zhí)行,使用channel,能夠使得任務(wù)的同步和順序執(zhí)行變得更加直觀和可管理。下面通過一個示例代碼,展示如何使用通道實(shí)現(xiàn)任務(wù)的有序執(zhí)行:
package main import "fmt" func taskA(waitCh chan<- string, resultCh chan<- string) { ? ? ? ? // 等待開始執(zhí)行 ? ? ? ? <- waitCh ? ? ? ? // 執(zhí)行任務(wù)A的邏輯 ? ? ? ? // ... ? ? ? ? // 將任務(wù)A的結(jié)果發(fā)送到通道 ? ? ? ? resultCh <- "任務(wù)A完成" } func taskB(waitCh <-chan string, resultCh chan<- string) { ? ? ? ? // 等待開始執(zhí)行 ? ? ? ? resultA := <-waitCh ? ? ? ? // 根據(jù)任務(wù)A的結(jié)果執(zhí)行任務(wù)B的邏輯 ? ? ? ? // ... ? ? ? ? // 將任務(wù)B的結(jié)果發(fā)送到通道 ? ? ? ? resultCh <- "任務(wù)B完成" } func taskC(waitCh <-chan string, resultCh chan<- string) { ? ? ? ? // 等待任務(wù)B的結(jié)果 ? ? ? ? resultB := <-waitCh ? ? ? ? // 根據(jù)任務(wù)B的結(jié)果執(zhí)行任務(wù)C的邏輯 ? ? ? ? // ... ? ? ? ? resultCh <- "任務(wù)C完成" } func main() { ? ? ? ? // 創(chuàng)建用于任務(wù)之間通信的通道 ? ? ? ? beginChannel := make(chan string) ? ? ? ? channelA := make(chan string) ? ? ? ? channelB := make(chan string) ? ? ? ? channelC := make(chan string) ? ? ? ? beginChannel <- "begin" ? ? ? ? // 啟動任務(wù)A ? ? ? ? go taskA(beginChannel, channelA) ? ? ? ? // 啟動任務(wù)B ? ? ? ? go taskB(channelA, channelB) ? ? ? ? // 啟動任務(wù)C ? ? ? ? go taskC(channelB,channelC) ? ? ? ? // 阻塞主線程,等待任務(wù)C完成 ? ? ? ? select {} ? ? ? ? // 注意:上述代碼只是示例,實(shí)際情況中可能需要適當(dāng)?shù)靥砑油讲僮骰蜿P(guān)閉通道的邏輯 }
在這個例子中,我們啟動了三個任務(wù),并通過通道進(jìn)行它們之間的通信來保證執(zhí)行順序。任務(wù)A等待beginChannel通道的信號,一旦接收到信號,任務(wù)A開始執(zhí)行并將結(jié)果發(fā)送到channelA通道。其他任務(wù),比如任務(wù)B,等待任務(wù)A完成的信號,一旦接收到channelA通道的數(shù)據(jù),任務(wù)B開始執(zhí)行。同樣地,任務(wù)C等待任務(wù)B完成的信號,一旦接收到channelB通道的數(shù)據(jù),任務(wù)C開始執(zhí)行。通過這種方式,我們實(shí)現(xiàn)了任務(wù)之間的有序執(zhí)行。
相對于使用sync.Cond的實(shí)現(xiàn)方式來看,通過使用通道,在任務(wù)之間進(jìn)行有序執(zhí)行時,代碼通常更加簡潔和易于理解。比如上面的例子,我們可以很清楚得識別出來,任務(wù)的執(zhí)行順序為 任務(wù)A ---> 任務(wù)B --> 任務(wù)C。
其次通道可以輕松地添加或刪除任務(wù),并調(diào)整它們之間的順序,而無需修改大量的同步代碼。這種靈活性使得代碼更易于維護(hù)和演進(jìn)。也是以上面的代碼例子為例,假如現(xiàn)在需要修改任務(wù)的執(zhí)行順序,將其執(zhí)行順序修改為 任務(wù)A ---> 任務(wù)C ---> 任務(wù)B,只需要簡單調(diào)整下順序即可,具體如下:
func main() { ? ? ? ? // 創(chuàng)建用于任務(wù)之間通信的通道 ? ? ? ? beginChannel := make(chan string) ? ? ? ? channelA := make(chan string) ? ? ? ? channelB := make(chan string) ? ? ? ? channelC := make(chan string) ? ? ? ? beginChannel <- "begin" ? ? ? ? // 啟動任務(wù)A ? ? ? ? go taskA(beginChannel, channelA) ? ? ? ? // 啟動任務(wù)B ? ? ? ? go taskB(channelC, channelB) ? ? ? ? // 啟動任務(wù)C ? ? ? ? go taskC(channelA,channelC) ? ? ? ? // 阻塞主線程,等待任務(wù)C完成 ? ? ? ? select {} ? ? ? ? // 注意:上述代碼只是示例,實(shí)際情況中可能需要適當(dāng)?shù)靥砑油讲僮骰蜿P(guān)閉通道的邏輯 }
和之前的唯一區(qū)別,只在于任務(wù)B傳入的waitCh參數(shù)為channelC,任務(wù)C傳入的waitCh參數(shù)為channelA,做了這么一個小小的變動,便實(shí)現(xiàn)了任務(wù)執(zhí)行順序的調(diào)整,非常靈活。
最后,相對于sync.Cond,通道提供了一種安全的機(jī)制來實(shí)現(xiàn)任務(wù)的有序執(zhí)行。由于通道在發(fā)送和接收數(shù)據(jù)時會進(jìn)行隱式的同步,因此不會出現(xiàn)數(shù)據(jù)競爭和并發(fā)訪問的問題。這可以避免潛在的錯誤和 bug,并提供更可靠的同步操作。
總的來說,如果是任務(wù)之間的簡單協(xié)調(diào),比如任務(wù)執(zhí)行順序的協(xié)調(diào)同步,通過通道來實(shí)現(xiàn)是非常合適的。通道提供了簡潔、可靠的機(jī)制,使得任務(wù)的有序執(zhí)行變得靈活和易于維護(hù)。
5. sync.Cond適用場景說明
在任務(wù)之間的簡單協(xié)調(diào)場景下,使用channel的同步實(shí)現(xiàn),相對于sync.Cond的實(shí)現(xiàn)是更為簡潔和易于維護(hù)的,但是并非意味著sync.Cond就無用武之地了。在一些相對復(fù)雜的同步場景下,sync.Cond相對于channel來說,表達(dá)能力是更強(qiáng)的,而且是更為容易理解的。因此,在這些場景下,雖然使用channel也能夠起到同樣的效果,使用sync.Cond可能相對來說也是更為合適的,即使sync.Cond使用起來更為復(fù)雜。下面我們來簡單講述下這些場景。
5.1 精細(xì)化條件控制
對于具有復(fù)雜的等待條件和需要精細(xì)化同步的場景,使用sync.Cond是一個合適的選擇。它提供了更高級別的同步原語,能夠滿足這種特定需求,并且可以確保線程安全和正確的同步行為。
下面舉一個簡單的例子,有一個主協(xié)程負(fù)責(zé)累加計數(shù)器的值,而存在多個等待協(xié)程,每個協(xié)程都有自己獨(dú)特的等待條件。等待協(xié)程需要等待計數(shù)器達(dá)到特定的值才能繼續(xù)執(zhí)行。
對于這種場景,使用sync.Cond來實(shí)現(xiàn)是更為合適的選擇。sync.Cond提供了一種基于條件的同步機(jī)制,可以方便地實(shí)現(xiàn)協(xié)程之間的等待和通知。使用sync.Cond,主協(xié)程可以通過調(diào)用Wait方法等待條件滿足,并通過調(diào)用Broadcast或Signal方法來通知等待的協(xié)程。等待的協(xié)程可以在條件滿足時繼續(xù)執(zhí)行任務(wù)。
相比之下,使用通道來實(shí)現(xiàn)可能會更加復(fù)雜和繁瑣。通道主要用于協(xié)程之間的通信,并不直接提供條件等待的機(jī)制。雖然可以通過在通道中傳遞特定的值來模擬條件等待,但這通常會引入額外的復(fù)雜性和可能的競爭條件。因此,在這種情況下,使用sync.Cond更為合適,可以更直接地表達(dá)協(xié)程之間的條件等待和通知,代碼也更易于理解和維護(hù)。下面來簡單看下使用sync.Cond實(shí)現(xiàn):
package main import ( ? ? ? ? "fmt" ? ? ? ? "sync" ) var ( ? ? ? ? counter int ? ? ? ? cond ? ?*sync.Cond ) func main() { ? ? ? ? cond = sync.NewCond(&sync.Mutex{}) ? ? ? ? // 啟動等待協(xié)程 ? ? ? ? for i := 0; i < 5; i++ { ? ? ? ? ? ? ? ? go waitForCondition(i) ? ? ? ? } ? ? ? ? // 模擬累加計數(shù)器 ? ? ? ? for i := 1; i <= 10; i++ { ? ? ? ? ? ? ? ? // 加鎖,修改計數(shù)器 ? ? ? ? ? ? ? ? cond.L.Lock() ? ? ? ? ? ? ? ? counter += i ? ? ? ? ? ? ? ? fmt.Println("Counter:", counter) ? ? ? ? ? ? ? ? cond.L.Unlock() ? ? ? ? ? ? ? ? cond.Broadcast() ? ? ? ? } } func waitForCondition(id int) { ? ? ? ? // 加鎖,等待條件滿足 ? ? ? ? cond.L.Lock() ? ? ? ? defer cond.L.Unlock() ? ? ? ? // 等待條件滿足 ? ? ? ? for counter < id*10 { ? ? ? ? ? ? ?cond.Wait() ? ? ? ? } ? ? ? ? // 執(zhí)行任務(wù) ? ? ? ? fmt.Printf("Goroutine %d: Counter reached %d\n", id, id*10) }
在上述代碼中,主協(xié)程使用sync.Cond的Wait方法等待條件滿足時進(jìn)行通知,而等待的協(xié)程通過檢查條件是否滿足來決定是否繼續(xù)執(zhí)行任務(wù)。每個協(xié)程執(zhí)行的計數(shù)器值條件都不同,它們會等待主協(xié)程累加的計數(shù)器值達(dá)到預(yù)期的條件。一旦條件滿足,等待的協(xié)程將執(zhí)行自己的任務(wù)。
通過使用sync.Cond,我們可以實(shí)現(xiàn)多個協(xié)程之間的同步和條件等待,以滿足不同的執(zhí)行條件。
因此,對于具有復(fù)雜的等待條件和需要精細(xì)化同步的場景,使用sync.Cond是一個合適的選擇。它提供了更高級別的同步原語,能夠滿足這種特定需求,并且可以確保線程安全和正確的同步行為。
5.2 需要反復(fù)喚醒所有等待協(xié)程
這里還是以上面的例子來簡單說明,主協(xié)程負(fù)責(zé)累加計數(shù)器的值,并且有多個等待協(xié)程,每個協(xié)程都有自己獨(dú)特的等待條件。這些等待協(xié)程需要等待計數(shù)器達(dá)到特定的值才能繼續(xù)執(zhí)行。在這種情況下,每當(dāng)主協(xié)程對計數(shù)器進(jìn)行累加時,由于無法確定哪些協(xié)程滿足執(zhí)行條件,需要喚醒所有等待的協(xié)程。這樣,所有的協(xié)程才能判斷是否滿足執(zhí)行條件。如果只喚醒一個等待協(xié)程,那么可能會導(dǎo)致另一個滿足執(zhí)行條件的協(xié)程永遠(yuǎn)不會被喚醒。
因此,在這種場景下,每當(dāng)計數(shù)器累加一個值時,都需要喚醒所有等待的協(xié)程,以避免某個協(xié)程永遠(yuǎn)不會被喚醒。這種需要重復(fù)調(diào)用Broadcast的場景并不適合使用通道來實(shí)現(xiàn),而是最適合使用sync.Cond來實(shí)現(xiàn)同步操作。
通過使用sync.Cond,我們可以創(chuàng)建一個條件變量,協(xié)程可以使用Wait方法等待特定的條件出現(xiàn)。當(dāng)主協(xié)程累加計數(shù)器并滿足等待條件時,它可以調(diào)用Broadcast方法喚醒所有等待的協(xié)程。這樣,所有滿足條件的協(xié)程都有機(jī)會繼續(xù)執(zhí)行。
因此,在這種需要重復(fù)調(diào)用Broadcast的同步場景中,使用sync.Cond是最為合適的選擇。它提供了靈活的條件等待和喚醒機(jī)制,確保所有滿足條件的協(xié)程都能得到執(zhí)行的機(jī)會,從而實(shí)現(xiàn)正確的同步操作。
6. 總結(jié)
同步操作在并發(fā)編程中起著關(guān)鍵的作用,用于確保協(xié)程之間的正確協(xié)調(diào)和共享數(shù)據(jù)的一致性。在選擇同步操作的實(shí)現(xiàn)方式時,我們有兩個常見選項:使用sync.Cond和通道。
使用sync.Cond和通道的方式提供了更高級、更靈活的同步機(jī)制。sync.Cond允許協(xié)程等待特定條件的出現(xiàn),通過Wait、Signal和Broadcast方法的組合,可以實(shí)現(xiàn)復(fù)雜的同步需求。通道則提供了直接的通信機(jī)制,通過發(fā)送和接收操作進(jìn)行隱式的同步,避免了數(shù)據(jù)競爭和并發(fā)訪問錯誤。
選擇適當(dāng)?shù)耐讲僮鲗?shí)現(xiàn)方式需要考慮具體的應(yīng)用場景。對于簡單的同步需求,可以使用通道方式。對于復(fù)雜的同步需求,涉及共享數(shù)據(jù)的操作,使用sync.Cond和可以提供更好的靈活性和安全性。
通過了解不同實(shí)現(xiàn)方式的特點(diǎn)和適用場景,可以根據(jù)具體需求選擇最合適的同步機(jī)制,確保并發(fā)程序的正確性和性能。
到此這篇關(guān)于go語言實(shí)現(xiàn)同步操作項目示例的文章就介紹到這了,更多相關(guān)go 同步操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang如何使用指針靈活操作內(nèi)存及unsafe包原理解析
本文將深入探討unsafe包的功能和原理,同時,我們學(xué)習(xí)某種東西,一方面是為了實(shí)踐運(yùn)用,另一方面則是出于功利性面試的目的,所以,本文還會為大家介紹unsafe?包的典型應(yīng)用以及高頻面試題,感興趣的朋友跟隨小編一起看看吧2024-07-07Golang詳細(xì)講解常用Http庫及Gin框架的應(yīng)用
下面這篇文章主要給大家介紹了關(guān)于Golang常用的Http庫及Gin框架,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06golang有用的庫及工具 之 zap.Logger包的使用指南
這篇文章主要介紹了golang有用的庫及工具 之 zap.Logger包的使用指南,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12Go語言學(xué)習(xí)之?dāng)?shù)組的用法詳解
數(shù)組是相同數(shù)據(jù)類型的一組數(shù)據(jù)的集合,數(shù)組一旦定義長度不能修改,數(shù)組可以通過下標(biāo)(或者叫索引)來訪問元素。本文將通過示例詳細(xì)講解Go語言中數(shù)組的使用,需要的可以參考一下2022-04-04golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法
這篇文章主要介紹了golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03GO Cobra Termui庫開發(fā)終端命令行小工具輕松上手
這篇文章主要為大家介紹了GO語言開發(fā)終端命令行小工具,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01