27. 學習 Go 協程:WaitGroup

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 是一種極不推薦的方式,今天主要就要來介紹 一下如何優雅的處理這種狀況。函數

1. 使用信道來標記完成

「不要經過共享內存來通訊,要經過通訊來共享內存」學習

學習了信道後,咱們知道,信道能夠實現多個協程間的通訊,那麼咱們只要定義一個信道,在任務完成後,往信道中寫入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

2. 使用 WaitGroup

上面使用信道的方法,在單個協程或者協程數少的時候,並不會有什麼問題,但在協程數多的時候,代碼就會顯得很是複雜,有興趣能夠本身嘗試一下。

那麼有沒有一種更加優雅的方式呢?

有,這就要說到 sync包 提供的 WaitGroup 類型。

WaitGroup 你只要實例化了就能使用

var 實例名 sync.WaitGroup

實例化完成後,就可使用它的幾個方法:

  • Add:初始值爲0,你傳入的值會往計數器上加,這裏直接傳入你子協程的數量
  • Done:當某個子協程完成後,可調用此方法,會從計數器上減一,一般可使用 defer 來調用。
  • Wait:阻塞當前協程,直到實例裏的計數器歸零。

舉一個例子:

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。。

系列導讀

01. 開發環境的搭建(Goland & VS Code)

02. 學習五種變量建立的方法

03. 詳解數據類型:****整形與浮點型

04. 詳解數據類型:byte、rune與string

05. 詳解數據類型:數組與切片

06. 詳解數據類型:字典與布爾類型

07. 詳解數據類型:指針

08. 面向對象編程:結構體與繼承

09. 一篇文章理解 Go 裏的函數

10. Go語言流程控制:if-else 條件語句

11. Go語言流程控制:switch-case 選擇語句

12. Go語言流程控制:for 循環語句

13. Go語言流程控制:goto 無條件跳轉

14. Go語言流程控制:defer 延遲調用

15. 面向對象編程:接口與多態

16. 關鍵字:make 和 new 的區別?

17. 一篇文章理解 Go 裏的語句塊與做用域

18. 學習 Go 協程:goroutine

19. 學習 Go 協程:詳解信道/通道

20. 幾個信道死鎖經典錯誤案例詳解

21. 學習 Go 協程:WaitGroup

22. 學習 Go 協程:互斥鎖和讀寫鎖

23. Go 裏的異常處理:panic 和 recover

24. 超詳細解讀 Go Modules 前世此生及入門使用

25. Go 語言中關於包導入必學的 8 個知識點

26. 如何開源本身寫的模塊給別人用?

27. 說說 Go 語言中的類型斷言?

28. 這五點帶你理解Go語言的select用法


相關文章
相關標籤/搜索