errgroup 使用

jsysjam · · 8487 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

errgroup 在 ```WaitGroup``` 的基础上实现子协程错误传递, 同时使用 context 控制协程的生命周期。 ## 使用 errgroup 的使用非常简单 ```go package main import ( "context" "fmt" "time" "golang.org/x/sync/errgroup" ) func main() { group, _ := errgroup.WithContext(context.Background()) for i := 0; i < 5; i++ { index := i group.Go(func() error { fmt.Printf("start to execute the %d gorouting\n", index) time.Sleep(time.Duration(index) * time.Second) if index%2 == 0 { return fmt.Errorf("something has failed on grouting:%d", index) } fmt.Printf("gorouting:%d end\n", index) return nil }) } if err := group.Wait(); err != nil { fmt.Println(err) } } ``` ### 输出 输出结果如下: start to execute the 0 gorouting start to execute the 3 gorouting start to execute the 2 gorouting start to execute the 1 gorouting start to execute the 4 gorouting gorouting:1 end gorouting:3 end something has failed on grouting:0 ### 代码分析 不管是否有协程执行失败, wait()都要等待所有协程执行完成 使用方法与 ```WaitGroup``` 类似。只是封装了 ```WaitGroup``` 的``` Add()```和 ```Wait()```方法。 * 首先传递 context 初始化 errgroup 对象 * 每一个 group.Go() 都会新启一个协程, ```Go()```函数接受一个 func() error 函数类型 * 使用 ```Wait()```方法阻塞主协程,直到所有子协程执行完成 ## 分析 errGroup 的结构如下: ```go type Group struct { cancel func() //context cancel() wg sync.WaitGroup errOnce sync.Once //只会传递第一个出现错的协程的 error err error //传递子协程错误 } ``` ### withContext ```go func WithContext(ctx context.Context) (*Group, context.Context) { ctx, cancel := context.WithCancel(ctx) return &Group{cancel: cancel}, ctx } ``` ### Go ```go func (g *Group) Go(f func() error) { 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() } }) } }() } ``` ### 小结 * errgroup 可以捕获和记录子协程的错误(只能记录最先出错的协程的错误) * errgroup 可以控制协程并发顺序。确保子协程执行完成后再执行主协程 * errgroup 可以使用 context 实现协程撤销。或者超时撤销。子协程中使用 ctx.Done()来获取撤销信号 ### 参考 [errgroup godoc](https://godoc.org/golang.org/x/sync/errgroup)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

8487 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传