sync/errgroup 用于 Go:完整指南及示例
\n\n1. 这是什么以及为什么需要它
\n\n 库 sync/errgroup 是官方扩展 golang.org/x/sync 的一部分,提供了一种强大而优雅的方式来管理带有错误处理的并发 goroutine。在 Go 的标准库中,有包含 WaitGroup 的 sync 包,但它无法收集来自 goroutine 的错误。errgroup 解决了这个问题:您启动多个 goroutine,如果其中至少有一个返回错误,该组会立即(或在所有 goroutine 完成后)发出信号,取消上下文并允许其他 goroutine 正常终止。\n
\n 为什么需要它?在实际应用中,通常需要并行执行多个独立任务:下载文件、处理数据、向 API 发出请求。如果一个任务因错误而失败,则没有理由继续其他任务——需要快速停止并向用户返回错误。errgroup 会自动执行此操作:您传递一个上下文,在第一个错误出现时,上下文被取消,所有监听此上下文的 goroutine 都可以提前终止。\n
\n 这在微服务、Web 服务器和 CLI 工具中尤其有用,因为在这些场景中,对错误的快速响应至关重要。与使用通道和 select 进行手动管理相比,errgroup 提供了一个简洁、声明式的 API,很难被误用。\n
2. 安装
\n\n sync/errgroup 不包含在 Go 标准库中,但它是子模块 golang.org/x/sync 的一部分。安装只需一条命令:\n
go get golang.org/x/sync/errgroup\n \n 之后,您可以在代码中导入该包:\n
\nimport "golang.org/x/sync/errgroup"\n \n 请确保您已安装 Go 1.13 或更高版本(建议使用 1.18+ 以支持泛型,尽管 errgroup 并未使用它们)。如果您使用模块(go.mod),go get 命令会自动更新 go.sum 文件。\n
3. 快速入门——最小工作示例
\n\n 下面是一个最简单的示例,它启动三个 goroutine,每个 goroutine 在传入的数字为负数时返回错误。如果至少有一个 goroutine 返回错误,errgroup.Wait() 将返回该错误。\n
package main\n\nimport (\n "context"\n "fmt"\n "golang.org/x/sync/errgroup"\n)\n\nfunc main() {\n g, ctx := errgroup.WithContext(context.Background())\n\n numbers := []int{1, -2, 3}\n for _, n := range numbers {\n n := n // 捕获变量\n g.Go(func() error {\n select {\n case <-ctx.Done():\n return ctx.Err()\n default:\n }\n if n < 0 {\n return fmt.Errorf("negative number: %d", n)\n }\n fmt.Printf("Processed %d\\n", n)\n return nil\n })\n }\n\n if err := g.Wait(); err != nil {\n fmt.Printf("Error: %v\\n", err)\n } else {\n fmt.Println("All tasks completed successfully")\n }\n}\n \n 输出:Processed 1,Processed 3,Error: negative number: -2。请注意,处理数字 3 的 goroutine 可能不会执行,如果上下文在其启动之前已被取消——这演示了早期停止机制。\n
4. 主要方法/函数
\n以下是 errgroup 包的所有关键 API 元素。每个方法都附有签名、说明和一个工作示例。