Why This Happens
Goroutine leaks happen when a goroutine blocks indefinitely on a channel operation, mutex lock, or other synchronization primitive and has no way to be cancelled. Over time this causes increasing memory usage and can crash your application. Use context cancellation or done channels to signal goroutines to exit.
The Problem
func process() {
ch := make(chan int)
go func() {
val := <-ch // blocks forever, nothing sends to ch
fmt.Println(val)
}()
// function returns, goroutine leaks
}The Fix
func process(ctx context.Context) {
ch := make(chan int)
go func() {
select {
case val := <-ch:
fmt.Println(val)
case <-ctx.Done():
return
}
}()
}Step-by-Step Fix
- 1
Identify the blocked goroutine
Use runtime.NumGoroutine() or pprof to find goroutines that are stuck and examine their stack traces.
- 2
Find the blocking operation
Determine which channel operation, mutex, or I/O call is preventing the goroutine from completing.
- 3
Add cancellation support
Use context.WithCancel or a done channel in a select statement so the goroutine can exit when no longer needed.
Bugsly catches this automatically
Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.
Try Bugsly free