sync.WaitGroup
Call `Add` before starting work, pair each increment with one `Done`, and keep ownership simple.
Canonical guidance
- call
Addbeforego - defer
Doneat the start of the goroutine - keep one clear owner for launch and one clear wait point
- on newer Go versions, consider
WaitGroup.Gowhen it makes launch ownership simpler
Use when
- waiting for sibling goroutines
- bounded background work
- simple fan-out without error propagation
Avoid
- calling
Addinside the goroutine - copying a
WaitGroup - mixing it with ad hoc shutdown rules nobody owns
Preferred pattern
var wg sync.WaitGroup
for _, job := range jobs {
wg.Add(1)
go func(job Job) {
defer wg.Done()
process(job)
}(job)
}
wg.Wait()
Anti-pattern
- racing
WaitagainstAddbecause work registration happens after launch
Explanation: This anti-pattern is tempting because the goroutine already “knows” it exists, but WaitGroup correctness depends on registration happening first.
Why
WaitGroupis simple only when lifecycle ownership stays simple
Related pages
Sources
- sync package - Go Team
- Misusing sync.WaitGroup (#71) - Teiva Harsanyi