Go 并发编排:用 errgroup 协同多 goroutine 与统一错误取消
test12026-09-120 次阅读
传统 WaitGroup 的局限
sync.WaitGroup 能等一组 goroutine 跑完,但它不处理错误,也无法在某个任务失败时通知其他任务取消。真实业务里往往要求"任意一个失败就整体失败",errgroup 正好补上这块。
errgroup 基础用法
package main
import (
"context"
"fmt"
"time"
"golang.org/x/sync/errgroup"
)
func fetch(ctx context.Context, url string) (string, error) {
select {
case <-time.After(50 * time.Millisecond):
return url, nil
case <-ctx.Done():
return "", ctx.Err()
}
}
func main() {
g, ctx := errgroup.WithContext(context.Background())
urls := []string{"a", "b", "c"}
res := make([]string, len(urls))
for i, u := range urls {
i, u := i, u
g.Go(func() error {
s, err := fetch(ctx, u)
if err != nil {
return err
}
res[i] = s
return nil
})
}
if err := g.Wait(); err != nil {
fmt.Println("部分任务失败:", err)
return
}
fmt.Println(res)
}
关键点解释
- errgroup.WithContext 返回一个带取消能力的 ctx,任意一个 g.Go 返回非 nil 错误,ctx 就会被取消。
- 循环里 i, u := i, u 是必要的,否则闭包捕获的是同一个循环变量。
- g.Wait 返回第一个非 nil 错误,其余 goroutine 因 ctx 取消而提前退出。
限制并发数
任务很多时,用带信号量的 errgroup 控制并发上限,避免瞬间打满下游:
func run(tasks []string, limit int) error {
g, ctx := errgroup.WithContext(context.Background())
ch := make(chan struct{}, limit)
for _, t := range tasks {
t := t
ch <- struct{}{}
g.Go(func() error {
defer func() { <-ch }()
return doWork(ctx, t)
})
}
return g.Wait()
}T
test1
文章作者
传统 WaitGroup 的局限 sync.WaitGroup 能等一组 goroutine 跑完,但它不处理错误,也...
- 分类
- 技术
- 发布时间
- 2026-09-12
- 字数
- 约 1308 字
- 阅读
- 0 次
