errgroup Patterns
errgroup Patterns
Overview
golang.org/x/sync/errgroup runs a set of goroutines and returns the first error, optionally canceling siblings via derived context. Prefer it over ad-hoc WaitGroup+mutex error slots for fan-out.
Diagram: cancel on first error
sequence (top → bottom):
actors: errgroup, task A, task B
errgroup --> task A : Go
errgroup --> task B : Go
task A --> errgroup : err
errgroup --> task B : ctx cancel
errgroup --> errgroup : Wait returns err
Basic API
g, ctx := errgroup.WithContext(parent)
g.Go(func() error {
return work(ctx)
})
g.Go(func() error {
return other(ctx)
})
if err := g.Wait(); err != nil {
return err
}Limits
g.SetLimit(8) // max concurrent Gs in this group (modern x/sync)Bounds fan-out without a hand-rolled semaphore.
Rules
- Pass
ctxinto every blocking call - Return errors; do not log+ignore inside Go funcs without policy
Waitonce; do not reuse group- First error wins—others may still run until cancel observed
vs WaitGroup
| WaitGroup | errgroup | |
|---|---|---|
| Error prop | manual | built-in |
| Cancel siblings | manual | WithContext |
| Limit concurrency | manual | SetLimit |
Experiment
go get golang.org/x/sync/errgroupg, ctx := errgroup.WithContext(context.Background())
g.Go(func() error {
<-ctx.Done()
return ctx.Err()
})
g.Go(func() error {
return errors.New("boom")
})
fmt.Println(g.Wait())What to notice: First error cancels context; the other returns context.Canceled or exits promptly if it watches ctx.
Try next: Crawl N URLs with SetLimit(5) and a shared ctx timeout.