Go 并发实战:用 errgroup 控制一组 goroutine 的退出

后端Go 发布于 2026-07-26 · 分类:后端开发 · 阅读 1,532

一个抓取服务要并发请求 N 个上游,任何一个关键上游失败就应该整体取消、返回错误。裸用 sync.WaitGroup + 手动 context 取消很啰嗦,errgroup 正好解决这个。

g, ctx := errgroup.WithContext(context.Background())
for _, u := range urls {
    u := u
    g.Go(func() error {
        req, _ := http.NewRequestWithContext(ctx, "GET", u, nil)
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            return err          // 任一返回 error,ctx 会被取消
        }
        defer resp.Body.Close()
        return process(resp)
    })
}
if err := g.Wait(); err != nil {
    log.Fatal(err)
}

要点

常见泄漏坑

goroutine 里往无缓冲 channel 发送却没人接收、或者没监听 ctx.Done(),会导致任务结束后 goroutine 挂住。用 go test -race 和 pprof 的 goroutine profile 能很快发现这类泄漏。

— 本文为个人运维笔记,如有疏漏欢迎指正。