Горутинная утечка — это когда горутина запустилась и никогда не завершится. Она висит в памяти, ест ресурсы, а ты даже не знаешь о ней. Чаще всего это происходит, когда горутина заблокирована на чтении из канала, в который никто никогда не напишет.
// утечка: ch никто не закрывает, горутина висит вечно
func leak() {
ch := make(chan int)
go func() {
val := <-ch // заблокирована навсегда
fmt.Println(val)
}()
}
Найти утечку можно через runtime.NumGoroutine() — если число растёт со временем, значит что-то не завершается. Ещё помогает pprof: /debug/pprof/goroutine?debug=2 покажет стектрейсы всех горутин. В тестах используй goleak от Uber — он проверяет, что после теста не осталось лишних горутин. Лечение простое: всегда думай, как горутина завершится — через context, close(ch) или done-канал.