使用 errgroup 处理并发错误
实践 golang.org/x/sync/errgroup
使用 errgroup 处理并发错误 是 CoddyKit 上的免费 Go Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。
goroutine 和错误的问题
使用 go func() 启动 goroutine 会丢弃包括错误在内的返回值。您需要借助额外机制(通道、WaitGroup)来收集这些返回值。errgroup 可以简化这一过程。
golang.org/x/sync/errgroup
errgroup.Group 会运行 goroutine 并收集错误。Wait() 会阻塞,直到所有 goroutine 完成,然后返回第一个非 nil 错误。
var g errgroup.Group
g.Go(func() error { return fetchUsers() })
g.Go(func() error { return fetchOrders() })
if err := g.Wait(); err != nil {
log.Fatal(err)
}errgroup.WithContext
WithContext 会返回一个组和一个派生上下文。当第一个 goroutine 返回错误时,上下文会被取消,从而停止剩余工作。
g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error { return doWork(ctx) })
g.Go(func() error { return doOtherWork(ctx) })
err := g.Wait()同时收集结果和错误
errgroup 只收集错误,不收集结果。请将结果存入预先分配的切片,并通过索引访问,以避免同步:
results := make([]Result, len(items))
for i, item := range items {
i, item := i, item
g.Go(func() error {
r, err := process(ctx, item)
if err != nil { return err }
results[i] = r
return nil
})
}
if err := g.Wait(); err != nil { return err }g.SetLimit(Go 1.20+)
g.SetLimit(n) 会限制并发运行的 goroutine 数量——无需单独的通道即可充当内联信号量。
g.SetLimit(10) // at most 10 goroutines at once
for _, item := range items {
g.Go(func() error { return process(item) })
}g.TryGo
g.TryGo(f) 仅在 SetLimit 设置的限制允许时启动 goroutine。如果未启动,则返回 false。
只返回第一个错误
errgroup 只返回第一个错误。如果需要收集所有错误,请在每个 goroutine 内将错误收集到由互斥锁保护的切片中。
var mu sync.Mutex
var errs []error
g.Go(func() error {
if err := doWork(); err != nil {
mu.Lock(); errs = append(errs, err); mu.Unlock()
}
return nil
})与 sync.WaitGroup 的区别
WaitGroup 跟踪完成状态;errgroup 不仅跟踪完成状态,还会收集错误。当任何 goroutine 的失败都应被报告时,请优先使用 errgroup。
上下文取消传播
使用 errgroup.WithContext 时,派生上下文的取消信号会通知所有其他 goroutine 停止——这类似于发生第一个错误时取消的语义。
测试 errgroup 代码
在测试中,请使用 WithTimeout 创建上下文,以确保某个 goroutine 挂起时该组不会无限运行。
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
g, ctx := errgroup.WithContext(ctx)信号量替代方案
在 SetLimit 出现之前(Go < 1.20),可以在各个 goroutine 中使用带缓冲的通道作为信号量,以实现相同效果。
快速检查
errgroup.WithContext 会返回什么,而普通的 errgroup.Group 不会返回什么?
回顾:errgroup
要点:
- g.Go(func() error)——启动 goroutine 并收集第一个错误
- g.Wait()——阻塞直到全部完成;返回第一个错误
- WithContext——在第一个错误发生时取消上下文
- g.SetLimit(n)——限制并发 goroutine 数量(Go 1.20+)
用 AI 导师学习 Go — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 51
- 课程
- 203
常见问题解答
「使用 errgroup 处理并发错误」课时是免费的吗?
是的 — 「使用 errgroup 处理并发错误」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。
「使用 errgroup 处理并发错误」这节课中我会学到什么?
实践 golang.org/x/sync/errgroup 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Go Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 errgroup 处理并发错误」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Go Academy 课中编写并运行代码吗?
能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。