Hi,你們好,我是明哥。git
在本身學習 Golang 的這段時間裏,我寫了詳細的學習筆記放在個人我的微信公衆號 《Go編程時光》,對於 Go 語言,我也算是個初學者,所以寫的東西應該會比較適合剛接觸的同窗,若是你也是剛學習 Go 語言,不防關注一下,一塊兒學習,一塊兒成長。github
個人在線博客:http://golang.iswbm.com
個人 Github:github.com/iswbm/GolangCodingTimegolang
在前兩篇文章裏,咱們學習了 協程
和 信道
的內容,裏面有不少例子,當時爲了保證 main goroutine 在全部的 goroutine 都執行完畢後再退出,我使用了 time.Sleep 這種簡單的方式。編程
因爲寫的 demo 都是比較簡單的, sleep 個 1 秒,咱們主觀上認爲是夠用的。數組
但在實際開發中,開發人員是沒法預知,全部的 goroutine 須要多長的時間才能執行完畢,sleep 多了吧主程序就阻塞了, sleep 少了吧有的子協程的任務就無法完成。微信
所以,使用time.Sleep 是一種極不推薦的方式,今天主要就要來介紹 一下如何優雅的處理這種狀況。函數
「不要經過共享內存來通訊,要經過通訊來共享內存」學習
學習了信道後,咱們知道,信道能夠實現多個協程間的通訊,那麼咱們只要定義一個信道,在任務完成後,往信道中寫入true,而後在主協程中獲取到true,就認爲子協程已經執行完畢。3d
import "fmt" func main() { done := make(chan bool) go func() { for i := 0; i < 5; i++ { fmt.Println(i) } done <- true }() <-done }
輸出以下指針
0 1 2 3 4
上面使用信道的方法,在單個協程或者協程數少的時候,並不會有什麼問題,但在協程數多的時候,代碼就會顯得很是複雜,有興趣能夠本身嘗試一下。
那麼有沒有一種更加優雅的方式呢?
有,這就要說到 sync包 提供的 WaitGroup 類型。
WaitGroup 你只要實例化了就能使用
var 實例名 sync.WaitGroup
實例化完成後,就可使用它的幾個方法:
舉一個例子:
import ( "fmt" "sync" ) func worker(x int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 5; i++ { fmt.Printf("worker %d: %d\n", x, i) } } func main() { var wg sync.WaitGroup wg.Add(2) go worker(1, &wg) go worker(2, &wg) wg.Wait() }
輸出以下
worker 2: 0 worker 2: 1 worker 2: 2 worker 2: 3 worker 2: 4 worker 1: 0 worker 1: 1 worker 1: 2 worker 1: 3 worker 1: 4
以上就是咱們在 Go 語言中實現一主多子的協程協做方式,推薦使用 sync.WaitGroup。。
系列導讀
24. 超詳細解讀 Go Modules 前世此生及入門使用