errgroup.group 必须用 errgroup.withcontext 初始化,不能直接 struct 初始化;其 go 方法启动 func() error 任务,wait 返回首个非 nil 错误,未完成任务需 context 控制取消。

errgroup.Group 的基本用法和初始化
直接用 errgroup.Group{} 初始化是错的——它内部有未导出字段,必须用 errgroup.WithContext 创建。否则调用 Go 或 Wait 会 panic。
正确方式是传入一个 context.Context,哪怕只是 context.Background():
g, _ := errgroup.WithContext(context.Background())
注意:返回的第二个值是 error,但 WithContext 实际上不会返回错误,可以安全忽略;不过不能省略接收,否则编译失败。
并发执行任务并收集第一个非nil错误
errgroup.Group 默认行为是“只要有一个 goroutine 返回非 nil error,Wait 就立刻返回该错误”,且其他 goroutine 不会自动取消——除非你显式用了带 cancel 的 context。
- 每个任务函数签名必须是
func() error,不能带参数,需靠闭包捕获变量 - 如果多个 goroutine 同时返回错误,
Wait只返回**第一个被发现的**(不是最先发生的),顺序取决于调度 - 未完成的 goroutine 会继续运行,直到自然结束或被 context 取消
示例:
g, ctx := errgroup.WithContext(context.Background()) for i := 0; i <h3>如何让失败任务自动取消其余 goroutine</h3><p>靠 <code>errgroup.Group</code> 自身做不到——它不主动控制 context。必须把同一个 <code>context.Context</code> 传给所有子任务,并在 goroutine 内监听 <code>ctx.Done()</code>。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0"><img src="https://img.php.cn/upload/manual/001/589/237/6a6adeed24a4a355.png" alt="Go语言(Golang)1.26.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0" class="overflowclass">Go语言(Golang)1.26.0</a> <p class="overflowclass">Go语言(Golang)1.26.0版本官方下载,版本号 1.26.0,适合旧项目维护、兼容性测试和指定版本开发环境搭建。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2525" title="Go语言(Golang)1.26.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><p>关键点:</p>
- 用
context.WithCancel包裹原始 context,得到可取消的子 context - 把子 context 传进每个 goroutine,在 I/O 或阻塞操作前加
select { case - 当任意 goroutine 报错,
Wait返回后,记得调用cancel()(但errgroup不帮你做这事)
所以典型模式是:
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 防止泄漏,但实际取消时机要手动控制
<p>g, <em> := errgroup.WithContext(ctx)
for </em>, url := range urls {
url := url
g.Go(func() error {
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// ...
return nil
})
}</p><p>if err := g.Wait(); err != nil {
cancel() // 主动触发取消,让其余 goroutine 尽快退出
return err
}
</p>
常见错误:误用无 context 版本或忽略 goroutine 泄漏
Go 标准库没有提供无 context 的 errgroup.Group 构造函数——网上有些旧代码写 var g errgroup.Group 是无效的,因为 Go 方法会 panic。
另一个高发问题是:没对耗时操作加 context 超时或取消,导致即使某个 goroutine 失败了,其余还在死等网络、文件读取或 sleep,整个 Wait 被拖住。
- 永远不要裸用
time.Sleep,改用select { case - HTTP 请求必须用
http.NewRequestWithContext,数据库查询也要传 context - 如果任务本身不支持 context(比如纯计算),就无法真正中断,只能等它跑完
最易被忽略的一点:errgroup 不负责资源清理,goroutine 里打开的文件、连接、goroutine 自身都得自己关、自己停、自己回收。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










