Stage 3 · Build
Concurrency in Depth
Goroutine Lifecycle
Spawn costs, leaks, ownership, and detecting blocked goroutines with stack dumps.
Goroutine Creation
Goroutines are cheap — they start at a few KB of stack and grow as needed. But they are not free. Each goroutine consumes memory, CPU time for scheduling, and GC overhead. Creating millions of goroutines is a bug, not a feature.
Ownership Model
Every goroutine needs a clear owner. The owner is responsible for starting the goroutine and ensuring it stops. Without ownership, goroutines leak because nobody is responsible for stopping them.
Goroutine Leaks
A goroutine leak is a goroutine that runs forever because it is waiting on a channel that will never receive, or a context that will never be canceled.
Detecting Leaks
Detect leaks in tests with goleak, in production with runtime.NumGoroutine(), and in debugging with stack dumps.
Stack Dumps
Stack dumps show where every goroutine is blocked. This is the most powerful tool for debugging goroutine leaks and deadlocks.
Best Practices
- Always provide an exit path for every goroutine
- Use context cancellation as the primary shutdown mechanism
- Monitor runtime.NumGoroutine() in production
- Use goleak in tests to catch leaks early
- Use errgroup for managed goroutine groups
- Set goroutine limits with errgroup.SetLimit or semaphores
- Document goroutine ownership in code comments
The most reliable pattern is tying goroutine lifetime to context lifetime. When the context is canceled, the goroutine exits. This creates a clear, testable lifecycle for every goroutine.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.