Preventing and Detecting Goroutine Leaks
Common leak patterns in Go concurrency and how to audit them with tooling.
In Go, starting a goroutine is as simple as the go keyword. But an abandoned goroutine that never exits is a permanent memory leak — its stack and heap allocations cannot be reclaimed by the garbage collector.
The Classic Nil Channel / Blocked Receive Leak
func QueryFirst(ctx context.Context, urls []string) string {
ch := make(chan string) // Unbuffered!
for _, url := range urls {
go func(u string) {
ch <- fetch(u) // Blocked forever if context cancels or first response wins!
}(url)
}
return <-ch
}
Detection Tools
go.uber.org/goleak: Catch leaked goroutines in unit tests before merging tomain:func TestMain(m *testing.M) { goleak.VerifyTestMain(m) }- Runtime metrics: Track
runtime.NumGoroutine()in production dashboards to spot upward-trending slopes.
See also the full guide on managing lifecycles in the blog: Managing Goroutine Lifecycles in Go.
Backlinks (3)