A goroutine that's blocked forever on a channel send/receive leaks — it's never garbage-collected. Always pair channels with `select { case <-ctx.Done(): return }` to give them an exit path.
`go fn()` spawns a goroutine. To wait for several to finish, use `sync.WaitGroup` — call `Add` before spawning, `Done` (deferred) inside, `Wait` to block until all are done.