欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang基于errgroup實現(xiàn)并發(fā)調用的方法

 更新時間:2022年09月05日 08:57:19   作者:夏日白云  
這篇文章主要介紹了golang基于errgroup實現(xiàn)并發(fā)調用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

串行調用

在用go編寫web/rpc服務器的時候,經常會出現(xiàn)需要對下游多 個/組 服務調用rpc(或者其他比較耗時的操作)的情況。
按照自然的寫法,比如對下游有ABC三個調用,串行順著寫,就總共要花費TimeA+TimeB+TimeC的時間:

func Handler(ctx context.Context) {
    var a, b, c respType
    a = A(ctx)
    b = B(ctx)
    c = C(ctx)
}

基于sync.WaitGroup實現(xiàn)簡單的并發(fā)調用

但經常地,幾個rpc相互之間沒有依賴關系的情況,這時,我們稍加思考就會想到使用并發(fā)的方式,同時發(fā)出請求,阻塞等到所有請求返回,這樣,總體耗時就變成了Max(TimeA, TimeB, TimeC),我們可以通過常用的sync.WaitGroup輕松實現(xiàn)這事:

func Handler(ctx context.Context) {
    var a, b, c respType
   	wg := sync.WaitGroup{}
	wg.Add(3)
	go func() {
		defer wg.Done()
		a = A(ctx)
	}()
	go func() {
		defer wg.Done()
		b = B(ctx)
	}()
	go func() {
		defer wg.Done()
		c = C(ctx)
	}()
	wg.Wait()
}

但是現(xiàn)實事件是不完美的,尤其是在加入了網(wǎng)絡這一因素后,我們經常會需要處理調用失敗的情況,很多情況下,并發(fā)的幾個操作只要任一失敗,整個處理就算失敗了,但是由于WaitGroup要等所有調用都done才能返回,因此調用時間是由耗時最長的那個(不一定是失敗的)決定的,如果不是失敗的那個,其實就產生了資源浪費,如下圖,B最先失敗了,此時邏輯上已經可以返回,但是實際卻等到了最長的調用-A返回了整個函數(shù)才返回:

func Handler(ctx context.Context) {
    var a, b, c respType
    var errA, errB, errC error
   	wg := sync.WaitGroup{}
	wg.Add(3)
	go func() {
		defer wg.Done()
		a, errA = A(ctx)
	}()
	go func() {
		defer wg.Done()
		b, errB = B(ctx)
	}()
	go func() {
		defer wg.Done()
		c, errC = C(ctx)
	}()
	wg.Wait()
	if errA != nil {
	// ...
	}
	if errB != nil {
	// ...
	}
	if errC != nil {
	// ...
	}
}

基于errgroup.Group實現(xiàn)并發(fā)調用

這對于追求極致的我們來說顯然是不能接受的,我們希望達到,如果有任意一個調用報錯,立刻讓所有調用返回的效果:

好在,我們有現(xiàn)成的工具可以用,通過引入"golang.org/x/sync/errgroup",可以輕松實現(xiàn)上面的目的。

為了使用errgroup,先使用WithContext方法創(chuàng)建一個Group

wg, groupCtx := errgroup.WithContext(ctx)

返回的第一個參數(shù)是*errgroup.Group,第二個則是在子調用中應該使用的context。

然后,使用Go方法調用所有的并發(fā)方法

	wg.Go(func() error {
		var err error
		a, err = A(groupCtx)
		return err
	})

最后, 使用Wait方法等待并發(fā)結束,返回值是所有子調用中第一個非nil的error,全成功的話就是nil。

if err := wg.Wait(); err != nil {
// ...
}

因此整體,我們的代碼差不多就長這個樣子

func handler(ctx context.Context) {
    var a, b, c respType
    wg, groupCtx := errgroup.WithContext(ctx)
	wg.Go(func() error {
		var err error
		a, err = A(groupCtx)
		return err
	})
	wg.Go(func() error {
		var err error
		b, err = B(groupCtx)
		return err
	})
	wg.Go(func() error {
		var err error
		c, err = C(groupCtx)
		return err
	})
	if err := wg.Wait(); err != nil {
    // ... 錯誤處理
    }
    // 全部成功
}

errgroup內部通過封裝了waitGroup和sync.Once實現(xiàn)了這個語法糖。

使用時特別要注意的是,errgroup的提前取消調用rpc是通過cancel那個返回的context(即上面的groupCtx)實現(xiàn)的,因此在所有子調用中都要實現(xiàn)監(jiān)聽groupCtx的Done事件。而在正常的rpc框架中都已經幫我們實現(xiàn)了這件事,因此我們只要保證傳進去的是groupCtx即可。

總結

errgroup幫我們封裝了并發(fā)調用下游時快速失敗的邏輯,我們能很方便地使用它進行業(yè)務代碼的編寫。使用的關鍵是一定要記得在子調用中傳遞WithContext中返回的Context。

好用的工具千千萬,讓我們一個個來掌握!

相關文章

  • Golang利用Template模板動態(tài)生成文本

    Golang利用Template模板動態(tài)生成文本

    Go語言中的Go?Template是一種用于生成文本輸出的簡單而強大的模板引擎,它提供了一種靈活的方式來生成各種格式的文本,下面我們就來看看具體如何使用Template實現(xiàn)動態(tài)文本生成吧
    2023-09-09
  • Golang配置管理庫?Viper的教程詳解

    Golang配置管理庫?Viper的教程詳解

    這篇文章主要介紹了Golang?配置管理庫?Viper,使用?viper?能夠很好的去管理你的配置文件信息,比如數(shù)據(jù)庫的賬號密碼,服務器監(jiān)聽的端口,你可以通過更改配置文件去更改這些內容,而不用定位到那一段代碼上去,提高了開發(fā)效率,需要的朋友可以參考下
    2022-05-05
  • Go 語言中的 http.FileSystem詳細解析

    Go 語言中的 http.FileSystem詳細解析

    在本文中,我們深入探討了 Go 語言中的 http.FileSystem 接口,并介紹了它的基本原理、使用方法以及實際應用場景,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Go 語言結構實例分析

    Go 語言結構實例分析

    在本篇文章里小編給大家整理的是一篇關于Go 語言結構實例分析的相關知識點,有興趣的朋友們可以學習下。
    2021-07-07
  • Go Module常用命令及如何使用Go Module

    Go Module常用命令及如何使用Go Module

    go module是go官方自帶的go依賴管理庫,在1.13版本正式推薦使用,這篇文章主要介紹了Go Module常用命令及如何使用Go Module,需要的朋友可以參考下
    2024-02-02
  • golang package time的用法具體詳解

    golang package time的用法具體詳解

    本篇文章主要介紹了golang package time的用法具體詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • 利用go-zero在Go中快速實現(xiàn)JWT認證的步驟詳解

    利用go-zero在Go中快速實現(xiàn)JWT認證的步驟詳解

    這篇文章主要介紹了如何利用go-zero在Go中快速實現(xiàn)JWT認證,本文分步驟通過實例圖文相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-10-10
  • go語言中五種字符串的拼接方式(小結)

    go語言中五種字符串的拼接方式(小結)

    字符串拼接在 golang 里面其實有很多種實現(xiàn),本文就詳細的介紹一下go語言中五種字符串的拼接方式以及性能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Golang實現(xiàn)四種負載均衡的算法(隨機,輪詢等)

    Golang實現(xiàn)四種負載均衡的算法(隨機,輪詢等)

    本文介紹了示例介紹了Golang 負載均衡的四種實現(xiàn),主要包括了隨機,輪詢,加權輪詢負載,一致性hash,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Go設計模式之策略模式講解和代碼示例

    Go設計模式之策略模式講解和代碼示例

    策略是一種行為設計模式,?它將一組行為轉換為對象,?并使其在原始上下文對象內部能夠相互替換,本文就將通過代碼示例給大家詳細的介紹一下Go的策略模式,需要的朋友可以參考下
    2023-08-08

最新評論