In all four boxes, the green line adds one more way out Four leaks · none has a way out They block in different places; each fix adds a way out 1Send with no receivergo func() { ch <- v }()✓ buffer of 1, or select on ctx.Done() 2range over an unclosed channelfor v := range ch { … }✓ the sender does defer close(ch) 3select that ignores cancelselect { case v := <-ch: … }✓ add case <-ctx.Done(): return 4Add and Done don't matchwg.Add(2) … one Done()✓ defer wg.Done() on the first line Go · ConceptsGo goroutine leaks and pprofchannels, mutexes, and exit pathsStarting a goroutine is easy. The hard part was deciding who changes the data, who finishes the work, and when a function may return.Oct 6, 2026