Explanation
What just happened
go worker(i) starts a goroutine and returns right away. main didn’t wait for anything: it printed and returned while all three workers were still in time.Sleep. In Go, main returning ends the program, so the workers died mid-sleep. Their Println never ran.
Nothing tells you. No panic, no warning, exit code 0.
Try the what-if switch
- wg.Wait(): a
sync.WaitGroupcounts running workers.wg.Add(1)before eachgo,wg.Done()as each one returns, andwg.Wait()blocksmainuntil the count is back to 0. A goroutine dump showsmainas[sync.WaitGroup.Wait].
Why it works like this
Goroutines are cheap and have no owner. Go doesn’t track which ones you still care about, so it can’t wait for them for you. Waiting is your job: a WaitGroup, a channel, or errgroup.
Watch out
Call wg.Add before go, never inside the goroutine. The workers’ print order changes from run to run; only “all done” is sure to come last.
Common questions
Why does my goroutine not print anything?
Because main returned first. When main returns, the whole program exits at once, and Go doesn't wait for other goroutines. There's no error and the exit code is 0.
How do I wait for goroutines to finish?
Use a sync.WaitGroup: call wg.Add(1) before each go, defer wg.Done() in the goroutine, and wg.Wait() in main. Since Go 1.25, wg.Go(f) does the Add and Done for you.
Can I call wg.Add inside the goroutine?
No. The goroutine may not have started when main reaches wg.Wait(), so the counter is still 0 and Wait returns at once. Call wg.Add before the go statement.
Verified: this timeline matches a real program, checked in CI on Go 1.26 and 1.27. How we verify. Unclear or wrong? Tell us