errgroup是一个很简单的工具包,总共代码量加上注释和空行才100来行

作用就是方便执行的任务,比如

g := errgroup.Group{}
g.Go(func1)
g.Go(func2)
if err := g.Wait(); err != nil {
  //...
}

结构

type Group struct {
	cancel func()     //context 取消函数
	wg sync.WaitGroup //用来等待全部执行完成
	sem chan token    //用来控制并发数
	errOnce sync.Once //控制err字段只赋值一次
	err     error     //错误
}

主要函数

func (g *Group) Go(f func() error) {
	if g.sem != nil {
		g.sem <- token{} //限制并发数, 并发数由管道能容纳下的token个数决定
	}

	g.wg.Add(1)
	go func() {
		defer g.done()

		if err := f(); err != nil {
			g.errOnce.Do(func() { //如果出错后只赋值一次err
				g.err = err
				if g.cancel != nil { //如果使用的是WithContext,这个字段会有值, 调用取消函数
					g.cancel()
				}
			})
		}
	}()
}

主要的东西就这么点, 可以看到errgroup还是一个很简洁的小工具, 配合singleflight一起使用挺不错