liveBook · Manning

WaitGroup

As explained in 100 Go Mistakes and How to Avoid Them

sync.WaitGroup is a Go synchronization type that allows code to wait for a specified number of concurrent operations to complete.

A sync.WaitGroup lets code wait for a specified number of operations, usually goroutines, to finish. Its zero value is ready to use: Add increments an internal counter, Done decrements it, and Wait blocks until the counter reaches zero. A negative counter panics. section 9.11

A common mistake is calling Add inside the goroutine it is meant to track. The parent may reach Wait before that Add executes, observe a zero counter, and continue while work is still running. The result can be nondeterministic, and the race detector may report unsafe access. section 9.11

Register work before starting it

Problematic code calls wg.Add(1) inside each goroutine, so wg.Wait can return too early. Register all work first, or increment immediately before each go statement: wg.Add(3) for i := 0; i < 3; i++ { go func() { // work wg.Done() }() } wg.Wait() For a loop, the equivalent pattern is wg.Add(1) followed immediately by go func(...). Use the first form when the total is known; use the second when launching work incrementally. section 9.11

wg := sync.WaitGroup{}
var v uint64
 
for i := 0; i < 3; i++ {
    go func() {                     #1
        wg.Add(1)                   #2
        atomic.AddUint64(&v, 1)     #3
        wg.Done()                   #4
    }()
}
 
wg.Wait()                           #5
fmt.Println(v)

Trace how Add inside the goroutine allows Wait to unlock before all three operations register. section 9.11

Use WaitGroup for completion synchronization, not for result collection or error handling. For coordinated cancellation and error propagation, errgroup is identified as an alternative; channels and sync.Cond provide other synchronization patterns. section 9.15

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains the zero value, counter operations, blocking Wait, panic condition, and Add-ordering failure, but not implementation internals.
Examples
Demonstrates three goroutines updating an atomic counter, premature Wait completion, and corrected Add-before-go patterns.
What it assumes
Assumes familiarity with goroutines and basic synchronization, while defining the WaitGroup counter and zero-value behavior.
What you can do after
Diagnose/debug with it by placing Add before goroutine creation and checking race-detector reports for premature completion.
How it connects
Connects WaitGroup with goroutines, atomic operations, channels, sync.Cond, errgroup, contexts, and the race detector.

Also explained in

Compare how 5 books explain WaitGroup →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.