We break down why
goroutine by themselves do not “keep” the program alive, and how to correctly wait for them to finish using
sync.WaitGroup. We lock in the contract:
wg.Add(...) — before launching via
go,
wg.Done() — inside the goroutine (preferably via
defer),
wg.Wait() — at the waiting point. Plus patterns (one task, a batch of tasks in a loop, passing
WaitGroup by pointer) and typical mistakes:
Add “in the wrong place”, a forgotten
Done, a negative counter, and accidental copying of the struct.