【Go并发编程】ErrGroup

212 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情

ErrGroup

errgroup.Group 是 Go 标准库 golang.org/x/sync/errgroup 包中提供的一种处理多个 Go 协程并行执行时发生错误的工具。

在多个协程并行执行任务时,如果有一个协程发生了错误,其它协程可能还在继续执行,这时候需要一种机制来取消所有协程的执行并返回错误信息。errgroup.Group 就是提供了这样的机制。

errgroup.Group 类似于一个任务组,你可以将多个任务添加到这个任务组中,任务组会并发执行这些任务。如果其中一个任务发生了错误,任务组会取消其它任务的执行并返回该任务的错误信息。因此,使用 errgroup.Group 可以很方便地处理多个协程并行执行时的错误。

func main() {
   // 创建 errgroup.Group 对象
   g := new(errgroup.Group)

   // 在 errgroup 中添加多个任务
   g.Go(func() error {
      return task1()
   })
   g.Go(func() error {
      return task2()
   })
   g.Go(func() error {
      return task3()
   })

   // 等待所有任务执行完成
   if err := g.Wait(); err != nil {
      fmt.Printf("Error occurred: %s\n", err.Error())
   }
}

func task1() error {
   // 任务 1 的逻辑
   return nil
}

func task2() error {
   // 任务 2 的逻辑
   return errors.New("task2 failed")
}

func task3() error {
   // 任务 3 的逻辑
   return nil
}

使用教程

创建一个 Group 对象时,需要使用 WithContext 方法:

func WithContext(ctx context.Context) (*Group, context.Context)

Group 的零值也是合法的,只不过,你就没有一个可以监控是否 cancel 的 Context 了。

Go:传入的子任务函数 f 是类型为 func() error 的函数,如果任务执行成功,就返回 nil,否则就返回 error,并且会 cancel 那个新的 Context。

func (g *Group) Go(f func() error)

Wait:类似 WaitGroup,Group 也有 Wait 方法,等所有的子任务都完成后,它才会返回,否则只会阻塞等待。如果有多个子任务返回错误,它只会返回第一个出现的错误,如果所有的子任务都执行成功,就返回 nil: func (g *Group) Wait() error

扩展库

  • bilibili/errgroup:可以使用一个固定数量的 goroutine 处理子任务。如果不设置 goroutine 的数量,那么每个子任务都会比较“放肆地”创建一个 goroutine并发执行。
    • cancel,失败的子任务可以 cancel 所有正在执行任务;
    • recover,而且会把 panic 的堆栈信息放到 error 中,避免子任务 panic 导致的程序崩溃。
  • neilotoole/errgroup:增加了可以控制并发 goroutine 的功能。
  • facebookgo/errgroup:一个可以返回error的waitgroup