errgroup 在 WaitGroup 的基础上实现子协程错误传递, 同时使用 context 控制协程的生命周期。

使用

errgroup 的使用非常简单

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 的结构如下:

type Group struct {
cancel func() //context cancel()
wg sync.WaitGroup
errOnce sync.Once //只会传递第一个出现错的协程的 error
err error //传递子协程错误
}

withContext

func WithContext(ctx context.Context) (*Group, context.Context) {
ctx, cancel := context.WithCancel(ctx)
return &Group{cancel: cancel}, ctx
}

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

errgroup 分析的更多相关文章

  1. drone的pipeline原理与代码分析

    最近的一个项目,需要实现一个工作任务流(task pipeline),基于之前CICD的经验,jenkins pipeline和drone的pipeline进入候选. drone是基于go的cicd解 ...

  2. 十二. Go并发编程--sync/errGroup

    一.序 这一篇算是并发编程的一个补充,起因是当前有个项目,大概の 需求是,根据kafka的分区(partition)数,创建同等数量的 消费者( goroutine)从不同的分区中消费者消费数据,但是 ...

  3. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  4. 火焰图分析openresty性能瓶颈

    注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...

  5. 一起来玩echarts系列(一)------箱线图的分析与绘制

    一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...

  6. 应用工具 .NET Portability Analyzer 分析迁移dotnet core

    大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...

  7. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  8. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  9. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

随机推荐

  1. sql server 自增列,值突然增大1000的情况

    sql server 自增列,值突然增大1000的情况   解决方法: 1 打开配置管理器2左面点击sql服务3右面 右键点击SQL Server(MSSQLSERVER) 4点击 启动参数5 在参数 ...

  2. python 二维码

    pip3 install Pillow pip3 install qrcode import qrcode text ="gisoracle我爱你呀" #input("输 ...

  3. laravel 通过ftp上传的时候报错 Use of undefined constant FTP_BINARY - assumed 'FTP_BINARY

    用Laravel中的filesystems里面的ftp上传文件时报错.在windows上开发,文件上传的时候碰到上面的问题,搜了些资料,发现是php7的ftp拓展默认未开启. filesystems是 ...

  4. python gdal ogr osgeo

  5. 【java/Json】用Java对象构建Json语法树

    本文后续:https://www.cnblogs.com/xiandedanteng/p/11973129.html 编译第一步:将文本解析成Java对象构成的语法树 第二步:将语法树输出整形好的Js ...

  6. Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别

    Oracle列信息表 all_tab_columns中的data_length和data_precision字段区别 区别: 这两个属性都属于user_tab_columns视图,他们的含义:1,da ...

  7. CentOS / RHEL 7 更改时区

    timedatectl 是 RHEL7 上的一项新功能.它可用于查询和更改系统时钟及其设置. 按照以下步骤将时区更改为中国.(以root用户身份执行以下命令). 1.使用以下命令列出所有可用的时区.你 ...

  8. typeScript模块<一>

    /*模块 模块的的概念 模块导出的几种方法 1.export 导出声明 2.export 导出语句 3.export default 4.import导入模块 模块化封装上一讲的DB库 */ /* 模 ...

  9. shell编程系列11--文本处理三剑客之sed利用sed删除文本中的内容

    shell编程系列11--文本处理三剑客之sed利用sed删除文本中的内容 删除命令对照表 命令 含义 1d 删除第一行内容 ,10d 删除1行到10行的内容 ,+5d 删除10行到16行的内容 /p ...

  10. Dart中的类型转换总结:

    1.Dart中数组转换为字符串:join var a=[1,2,3,4]; var str=a.join(',');