errgroup 分析
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 分析的更多相关文章
- drone的pipeline原理与代码分析
最近的一个项目,需要实现一个工作任务流(task pipeline),基于之前CICD的经验,jenkins pipeline和drone的pipeline进入候选. drone是基于go的cicd解 ...
- 十二. Go并发编程--sync/errGroup
一.序 这一篇算是并发编程的一个补充,起因是当前有个项目,大概の 需求是,根据kafka的分区(partition)数,创建同等数量的 消费者( goroutine)从不同的分区中消费者消费数据,但是 ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 火焰图分析openresty性能瓶颈
注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- 应用工具 .NET Portability Analyzer 分析迁移dotnet core
大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- ZIP压缩算法详细分析及解压实例解释
最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...
随机推荐
- Thingsboard MQTT连接至服务器
服务器地址加上1883端口号 用户中,需要增加设备的访问令牌 关于设备的访问令牌,可以选择设备的详细信息中,找到访问令牌 动图演示
- 深度学习面试题03:改进版梯度下降法Adagrad、RMSprop、Momentum、Adam
目录 Adagrad法 RMSprop法 Momentum法 Adam法 参考资料 发展历史 标准梯度下降法的缺陷 如果学习率选的不恰当会出现以上情况 因此有一些自动调学习率的方法.一般来说,随着迭代 ...
- Python_Openpyxl 浅谈(最全总结 足够初次使用)
https://blog.csdn.net/weixin_43094965/article/details/82226263 import datetime from random import ch ...
- nginx listen 端口 443 80 https 和 wss
端口号 443 和 80 端口的区别 一般指定 443 和 80 端口都是使用域名时所需要的 当我们使用域名请求时,一般是不添加端口号的 例如:http://www.baidu.com 在不添加端口号 ...
- (信贷风控九)行为评分卡模型python实现
python信用评分卡建模(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_ca ...
- AWS Fargate
AWS Lambda都是浮云,AWS Fargate才是王道——无服务器的未来,有我没你! - DockOne.iohttp://www.dockone.io/article/4656 通过 Farg ...
- openresty开发系列21--lua的模块
openresty开发系列21--lua的模块 从lua5.1开始,Lua 加入了标准的模块管理机制,Lua 的模块是由变量.函数等已知元素组成的 table, 因此创建一个模块很简单,就是创建一个 ...
- SeetaFaceEngine2 实例
LOG: Creating layer(6):LOG: Creating layer(0):LOG: Creating layer(9):LOG: Creating layer(0):LOG: Cre ...
- java使用Sonic 算法对音频变速不变声、变调、调整音量
依赖库:https://github.com/waywardgeek/sonic 基础库:Sonic.java /* Sonic library Copyright 2010, 2011 Bill C ...
- 原生JavaScript判断浏览器对CSS属性是否支持
/*判断浏览器是否支持某个css属性*/ function SupportCss(attrName){ var i=0, arr = SupportCss.opt.aBrowser, eleStyle ...