NOTE
2.2 sync.WaitGroup
Waiting for a group of goroutines to finish with Add, Done, and Wait, including the counter lifecycle and common Add/Wait misuse.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What Is sync.WaitGroup?
A WaitGroup lets one goroutine wait until a group of tasks has completed.
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
work1()
}()
go func() {
defer wg.Done()
work2()
}()
wg.Wait()
2. Mental Model
A WaitGroup maintains a counter:
Add(n)changes the counter byn;Done()is equivalent toAdd(-1);Wait()blocks until the counter reaches zero.
If the counter becomes negative, the program panics.
3. Correct Lifecycle
When starting a new group from a zero counter, positive Add calls should happen before the corresponding Wait can begin. The classic pattern is therefore:
wg.Add(1)
go func() {
defer wg.Done()
// work
}()
Putting Add(1) inside the new goroutine creates a race with Wait: the waiter may observe zero before the goroutine increments the counter.
A WaitGroup may be reused after a previous Wait has returned, but a WaitGroup must not be copied after first use.
4. WaitGroup vs. Context
WaitGroup coordinates completion; it does not cancel work or propagate errors. Combine it with context or a higher-level task-group abstraction when you also need cancellation/error propagation.