ErrGroup

main.go

package main

import (
 "context"
 "errors"
 "fmt"
 "time"

 "golang.org/x/sync/errgroup"
)

func task1(ctx context.Context) error {
 fmt.Println("Task 1 started successfully")
 select {
 case <-time.After(1 * time.Second):
  fmt.Println("Task 1 completed successfully")
  return nil
 case <-ctx.Done():
  fmt.Println("Task 1 canceled")
  return ctx.Err()
 }
}

func task2(ctx context.Context) error {
 fmt.Println("Task 2 started successfully")
 select {
 case <-time.After(2 * time.Second):
  fmt.Println("Task 2 processed failed")
  return errors.New("Task 2 processed failed due to error")
 case <-ctx.Done():
  fmt.Println("Task 2 canceled")
  return ctx.Err()
 }
}

func task3(ctx context.Context) error {
 fmt.Println("Task 3 started successfully")
 select {
 case <-time.After(3 * time.Second):
  fmt.Println("Task 3 completed successfully")
  return nil
 case <-ctx.Done():
  fmt.Println("Task 3 canceled")
  return ctx.Err()
 }
}

func main() {
 ctx, cancel := context.WithCancel(context.Background())
 defer cancel() // Ensure cancellation happens when main() exits

 g, ctx := errgroup.WithContext(ctx)

 g.Go(func() error {
  return task1(ctx)
 })

 g.Go(func() error {
  return task2(ctx)
 })

 g.Go(func() error {
  return task3(ctx)
 })

 if err := g.Wait(); err != nil {
  fmt.Println("Encountered error:", err)
  cancel()
 } else {
  fmt.Println("All tasks completed successfully")
 }
}

输出

Task 1 started successfully
Task 2 started successfully
Task 3 started successfully
Task 1 completed successfully
Task 2 processed failed
Encountered error: Task 2 processed failed due to error

ErrGroup vs WaitGroup

ErrGroup:

使用 ErrGroup 来管理并发任务中的错误。它聚合了所有协程中的错误,并返回遇到的第一个错误。
需要管理多个可能产生错误的并发任务。
想要利用上下文取消功能来优雅地关闭程序。
不想手动检查多个 WaitGroup 调用的错误
它与 Go 的上下文包无缝集成。任何来自协程的错误都会取消上下文,自动停止其他正在运行的任务。

WaitGroup

使用 WaitGroup 进行基本同步。它简单地等待指定数量的 goroutine 完成后再继续。
当你只关心任务完成而不预期错误时,它是理想的选择。
它不直接处理错误。你需要在每个 goroutine 中检查错误并单独处理它们。
posted @ 2024-05-14 10:59  朝阳1  阅读(3)  评论(0编辑  收藏  举报