patterngoModerate
WaitGroup pattern for fan-out goroutines
Viewed 0 times
WaitGroupsync.WaitGroupfan-outgoroutine waitparallel goroutineswg.Add wg.Done wg.Wait
Error Messages
Problem
Launching multiple goroutines and needing to wait for all of them to finish before proceeding is a common pattern without a clean built-in solution beyond WaitGroup.
Solution
Use sync.WaitGroup with Add before launching and Done in the goroutine:
func processAll(items []Item) {
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(it Item) {
defer wg.Done()
process(it)
}(item)
}
wg.Wait() // blocks until all goroutines call Done
}
// With error collection
func processAll(items []Item) error {
var (
wg sync.WaitGroup
mu sync.Mutex
errs []error
)
for _, item := range items {
wg.Add(1)
go func(it Item) {
defer wg.Done()
if err := process(it); err != nil {
mu.Lock()
errs = append(errs, err)
mu.Unlock()
}
}(item)
}
wg.Wait()
return errors.Join(errs...)
}Why
WaitGroup uses an internal counter. Add increments it, Done decrements it, and Wait blocks until the counter reaches zero. The counter must never go negative.
Gotchas
- Call wg.Add BEFORE launching the goroutine — calling it inside the goroutine creates a race with wg.Wait
- Never copy a WaitGroup after first use — pass by pointer or embed in a struct
- For error propagation, consider golang.org/x/sync/errgroup which combines WaitGroup with error handling
Revisions (0)
No revisions yet.