Go語言擴展原語之ErrGroup的用法詳解
概述
除標準庫中提供的同步原語外,Go語言還在子倉庫sync中提供了4種擴展原語:
golang/sync/errgroup.Groupgolang/sync/semaphore.Weightedgolang/sync/singleflight.Groupgolang/sync/syncmap.Map
其中 golang/sync/syncmap.Map 在 Go1.9 中移植到了標準庫中。
接下來介紹Go語言在擴展包中提供的3種同步原語 —— golang/sync/errgroup.Group
ErrGroup
golang/sync/errgroup.Group 為我們在一組 Goroutine 中提供了同步、錯誤傳播以及上下文取消功能,我們可以使用這種方式并行獲取網(wǎng)頁數(shù)據(jù):
var g errgroup.Group
var urls = []string{
"http://www.golang.org",
"http://www.google.com"
}
for i := range urls {
url := urls[i]
g.Go(func() error {
resp, err := http.Get(url)
if err == nil {
resp.Body.Close()
}
return err
})
}
if err := g.Wait(); err == nil {
fmt.Println("Successfully fetched all URLs.")
}golang/sync/errgroup.Group.Go 方法能夠創(chuàng)建一個 Goroutine 并在其中執(zhí)行傳入的函數(shù),而 golang/sync/errgroup.Group.Wait 會等待所有 Goroutine 返回,該方法的不同返回結(jié)果有不同的含義:
- 如果返回錯誤 —— 這一組
Goroutine最少返回一個錯誤 - 如果返回空值 —— 所有
Goroutine都成功執(zhí)行
結(jié)構(gòu)體
golang/sync/errgroup.Group 結(jié)構(gòu)體有 3 個比較重要的部分組成
cancel—— 創(chuàng)建context.Context時返回的取消函數(shù),用于在多個Goroutine之間同步取消信號wg—— 用于等待一組Goroutine完成子任務(wù)的同步原語errOnce—— 用于保證只接收一個子任務(wù)返回的錯誤
type Group struct {
cancel func()
wg sync.WaitGroup
errOnce sync.Once
err error
}這些字段共同組成了 golang/sync/errgroup.Group 結(jié)構(gòu)體并為我提供同步、錯誤傳播以及上下文取消等功能。
接口
我們能通過 golang/sync/errgroup.WithContext 構(gòu)造器創(chuàng)新的 golang/sync/errgroup.Group 結(jié)構(gòu)體:
func WithContext(ctx context.Context) (*Group, context.Context) {
ctx, cancel := context.WithCancel(ctx)
return &Group{cancel: cancel}, ctx
}運行新的并行子任務(wù)需要使用 golang/sync/errgroup.Group.Go 方法,這個方法的執(zhí)行過程如下:
- 調(diào)用
sync.WaitGroup.Add增加待處理的任務(wù) - 創(chuàng)建新的
Goroutine并運行子任務(wù) - 返回錯誤時及時調(diào)用
cancel并對err賦值,只有最早返回的錯誤才會被上游感知到,后續(xù)錯誤都會被舍棄。
func (g *Group) Go(){
g.wg.Add(1)
go func() {
defer g.wg.Done()
if err := f(); err := nil {
g.errOnce.Do(func () {
g.err = err
if g.cancel != nil {
g.cancel()
}
})
}
}()
}
func (g *Group) Wait() error {
g.wg.Wait()
if g.cancel != nil {
g.cancel()
}
return g.err
}另一個用于等待的 golang/sync/errgroup.Group.Wait 方法只是調(diào)用了 sync.WaitGroup.Wait,在子任務(wù)全部完成時取消 context.Context 并返回可能出現(xiàn)的錯誤。
小結(jié)
golang/sync/errgroup.Group 的實現(xiàn)沒有涉及底層和運行包中的API,它只是封裝了基本同步語義以提供更加復(fù)雜的功能。我們在使用它時需要注意兩個問題:
golang/sync/errgroup.Group在出現(xiàn)錯誤或者等待結(jié)束后,會調(diào)用context.Context的cancel方法同步取消信號- 只有第一個出現(xiàn)的錯誤才會被返回,剩余錯誤會被直接丟棄
到此這篇關(guān)于Go語言擴展原語之ErrGroup的用法詳解的文章就介紹到這了,更多相關(guān)Go ErrGroup內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go依賴注入DI工具wire使用詳解(golang常用庫包)
依賴注入是指程序運行過程中,如果需要調(diào)用另一個對象協(xié)助時,無須在代碼中創(chuàng)建被調(diào)用者,而是依賴于外部的注入,本文結(jié)合示例代碼給大家介紹Go依賴注入DI工具wire使用,感興趣的朋友一起看看吧2022-04-04

