Go基礎(chǔ)教程系列之WaitGroup用法實(shí)例詳解
正常情況下,新激活的goroutine(協(xié)程)的結(jié)束過(guò)程是不可控制的,唯一可以保證終止goroutine(協(xié)程)的行為是main goroutine(協(xié)程)的終止。也就是說(shuō),我們并不知道哪個(gè)goroutine(協(xié)程)什么時(shí)候結(jié)束。
但很多情況下,我們正需要知道goroutine(協(xié)程)是否完成。這需要借助sync包的WaitGroup來(lái)實(shí)現(xiàn)。
WatiGroup是sync包中的一個(gè)struct類型,用來(lái)收集需要等待執(zhí)行完成的goroutine(協(xié)程)。下面是它的定義:
type WaitGroup struct {
// Has unexported fields.
}
A WaitGroup waits for a collection of goroutines to finish. The main
goroutine calls Add to set the number of goroutines to wait for. Then each
of the goroutines runs and calls Done when finished. At the same time, Wait
can be used to block until all goroutines have finished.
A WaitGroup must not be copied after first use.
func (wg *WaitGroup) Add(delta int)
func (wg *WaitGroup) Done()
func (wg *WaitGroup) Wait()
它有3個(gè)方法:
- Add():每次激活想要被等待完成的goroutine(協(xié)程)之前,先調(diào)用Add(),用來(lái)設(shè)置或添加要等待完成的goroutine(協(xié)程)數(shù)量
- 例如Add(2)或者兩次調(diào)用Add(1)都會(huì)設(shè)置等待計(jì)數(shù)器的值為2,表示要等待2個(gè)goroutine(協(xié)程)完成
- Done():每次需要等待的goroutine(協(xié)程)在真正完成之前,應(yīng)該調(diào)用該方法來(lái)人為表示goroutine(協(xié)程)完成了,該方法會(huì)對(duì)等待計(jì)數(shù)器減1
- Wait():在等待計(jì)數(shù)器減為0之前,Wait()會(huì)一直阻塞當(dāng)前的goroutine(協(xié)程)
也就是說(shuō),Add()用來(lái)增加要等待的goroutine(協(xié)程)的數(shù)量,Done()用來(lái)表示goroutine(協(xié)程)已經(jīng)完成了,減少一次計(jì)數(shù)器,Wait()用來(lái)等待所有需要等待的goroutine(協(xié)程)完成。
下面是一個(gè)示例,通過(guò)示例很容易理解。
package main
import (
"fmt"
"sync"
"time"
)
func process(i int, wg *sync.WaitGroup) {
fmt.Println("started Goroutine ", i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n", i)
wg.Done()
}
func main() {
no := 3
var wg sync.WaitGroup
for i := 0; i < no; i++ {
wg.Add(1)
go process(i, &wg)
}
wg.Wait()
fmt.Println("All go routines finished executing")
}
上面激活了3個(gè)goroutine,每次激活goroutine之前,都先調(diào)用Add()方法增加一個(gè)需要等待的goroutine計(jì)數(shù)。每個(gè)goroutine都運(yùn)行process()函數(shù),這個(gè)函數(shù)在執(zhí)行完成時(shí)需要調(diào)用Done()方法來(lái)表示goroutine的結(jié)束。激活3個(gè)goroutine后,main goroutine會(huì)執(zhí)行到Wait(),由于每個(gè)激活的goroutine運(yùn)行的process()都需要睡眠2秒,所以main goroutine在Wait()這里會(huì)阻塞一段時(shí)間(大約2秒),當(dāng)所有g(shù)oroutine都完成后,等待計(jì)數(shù)器減為0,Wait()將不再阻塞,于是main goroutine得以執(zhí)行后面的Println()。
還有一點(diǎn)需要特別注意的是process()中使用指針類型的*sync.WaitGroup作為參數(shù),這里不能使用值類型的sync.WaitGroup作為參數(shù),因?yàn)檫@意味著每個(gè)goroutine都拷貝一份wg,每個(gè)goroutine都使用自己的wg。這顯然是不合理的,這3個(gè)goroutine應(yīng)該共享一個(gè)wg,才能知道這3個(gè)goroutine都完成了。實(shí)際上,如果使用值類型的參數(shù),main goroutine將會(huì)永久阻塞而導(dǎo)致產(chǎn)生死鎖。
更多關(guān)于Go WaitGroup用法教程請(qǐng)查看下面的相關(guān)鏈接
相關(guān)文章
Go微服務(wù)項(xiàng)目配置文件的定義和讀取示例詳解
這篇文章主要為大家介紹了Go微服務(wù)項(xiàng)目配置文件的定義和讀取示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
在 Golang 中實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Http中間件過(guò)程詳解
本文在go web中簡(jiǎn)單的實(shí)現(xiàn)了中間件的機(jī)制,這樣帶來(lái)的好處也是顯而易見的,當(dāng)然社區(qū)也有一些成熟的 middleware 組件,包括 Gin 一些Web框架中也包含了 middleware 相關(guān)的功能,具體內(nèi)容詳情跟隨小編一起看看吧2021-07-07
使用Golang調(diào)用攝像頭并進(jìn)行圖像處理
近年來(lái),攝像頭成為了我們生活中不可或缺的設(shè)備之一,從智能手機(jī)到安全監(jiān)控系統(tǒng),無(wú)處不在的攝像頭給我們帶來(lái)了便利和安全,在開發(fā)攝像頭相關(guān)的應(yīng)用程序時(shí),選擇一種高效和易用的編程語(yǔ)言是非常重要的,本文將介紹如何使用Golang調(diào)用攝像頭并進(jìn)行圖像處理2023-11-11
Go語(yǔ)言利用aicli實(shí)現(xiàn)輕松調(diào)用DeepSeek和ChatGPT
這篇文章主要為大家介紹了一款用Go語(yǔ)言編寫的AI助手客戶端庫(kù)——aicli,該庫(kù)不僅支持ChatGPT,還集成了DeepSeek,感興趣的小伙伴可以了解一下2025-03-03
GoAdminGroup/go-admin的安裝和運(yùn)行的教程詳解
這篇文章主要介紹了GoAdminGroup/go-admin的安裝和運(yùn)行的教程詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
GO中的時(shí)間操作總結(jié)(time&dateparse)
日常開發(fā)過(guò)程中,對(duì)于時(shí)間的操作可謂是無(wú)處不在,但是想實(shí)現(xiàn)時(shí)間自由還是不簡(jiǎn)單的,多種時(shí)間格式容易混淆,本文為大家整理了一下GO中的時(shí)間操作,有需要的可以參考下2023-09-09
Golang標(biāo)準(zhǔn)庫(kù)之errors包應(yīng)用方式
Go語(yǔ)言的errors包提供了基礎(chǔ)的錯(cuò)誤處理能力,允許通過(guò)errors.New創(chuàng)建自定義error對(duì)象,error在Go中是一個(gè)接口,通過(guò)實(shí)現(xiàn)Error方法來(lái)定義錯(cuò)誤文本,對(duì)錯(cuò)誤的比較通?;趯?duì)象地址,而非文本內(nèi)容,因此即使兩個(gè)錯(cuò)誤文本相同2024-10-10

