errgroup.Group
和 sync.WaitGroup
的主要区别在于它们的错误处理和协程管理方式。
errgroup.Group
专为并发操作中的错误捕获设计,任意goroutine返回错误时,会立即终止其他goroutine的执行。
而 sync.WaitGroup
主要用于等待多个 goroutine 完成,不会直接处理错误。
用法示例:
// errgroup
import ("fmt""golang.org/x/sync/errgroup"
)func main() {group := new(errgroup.Group)group.Go(func() error {// 模拟一个操作,可能会失败err := someOperation()if err != nil {return fmt.Errorf("operation failed: %v", err)}return nil})// 等待所有任务完成,并捕获错误if err := group.Wait(); err != nil {fmt.Println("任务执行中遇到错误:", err)} else {fmt.Println("所有任务执行完成")}
}
工作流程
- 调用
group.Go
添加需要并发执行的任务。 group.Wait()
会等待所有任务完成。如果某个 goroutine 返回错误,Wait
会返回该错误。errgroup
会终止错误出现后所有未完成的 goroutine,确保资源节省和异常处理的统一性。
优点
- 错误处理:直接返回错误,避免了手动捕获。
- 中止机制:在遇到错误后自动中止其他任务。
import ("fmt""sync"
)func main() {var wg sync.WaitGroupvar mu sync.Mutex // 用于防止并发访问results := make(map[int]string)for i := 1; i <= 5; i++ {wg.Add(1)go func(id int) {defer wg.Done()result, err := someOperation(id)mu.Lock()defer mu.Unlock() // 锁定操作以确保安全访问if err != nil {results[id] = fmt.Sprintf("error: %v", err)} else {results[id] = fmt.Sprintf("success: %v", result)}}(i)}wg.Wait()fmt.Println("所有操作完成", results)
}
errgroup.Group
与 sync.WaitGroup
的总结对比
特性 | errgroup.Group | sync.WaitGroup |
---|---|---|
错误处理 | 支持,返回第一个错误并中止其他任务 | 不支持,需手动处理 |
中止机制 | 出现错误后可中止其他任务 | 不支持 |
适合场景 | 并发任务中需统一错误处理 | 仅需等待所有任务完成 |
代码简洁性 | 更简洁,内置错误处理 | 需要手动处理错误和并发访问控制 |
底层实现 | 基于 sync.WaitGroup 进一步封装 | 基础并发任务等待工具 |
选择哪种方式取决于需求,若并发任务中需要统一的错误捕获和中止机制,errgroup.Group
是更好的选择;若仅需等待所有任务执行完毕,可使用 sync.WaitGroup
。