Перейти к содержимому
7 / 15

Утечки горутин: как возникают, чем грозят и как находить

Утечка горутины — горутина, которая никогда не завершится. В отличие от утечки памяти в языках без сборщика, здесь протекает не только стек: горутина удерживает всё, что захватила замыканием, поэтому одна зависшая горутина может держать мегабайты. Сборщик мусора её не соберёт — заблокированная горутина считается живой. Причин ровно три, и все сводятся к вечной блокировке. Отправка в канал, который никто не читает — типично, когда получатель ушёл по таймауту, а отправитель об этом не знает; лечится буфером на одно значение или select с ctx.Done(). Приём из канала, который никто не закроетrange по каналу без закрытия. Ожидание на WaitGroup, чей счётчик не дойдёт до нуля из-за потерянного Done. Находят утечки двумя способами: runtime.NumGoroutine() в мониторинге показывает монотонный рост, а pprof по адресу /debug/pprof/goroutine?debug=2 печатает стеки всех горутин с указанием, где именно они застряли.