Получить доступ

Что такое утечка горутин и как её избежать?

MiddleГорутины и каналы
Ещё спрашивают так:
  • Почему растёт число горутин в сервисе?
Коротко

Горутина, навсегда заблокированная на канале, мьютексе или вводе-выводе, никогда не завершится и держит стек и всё, на что ссылается. Типичные причины: отправка в канал, который никто не читает (вызывающий ушёл по таймауту), чтение из канала, который никто не закроет, сетевой вызов без таймаута.

  • У каждой горутины должен быть понятный способ завершиться
  • Отмена через context и select с ctx.Done()
  • Буфер на 1 для результата позволяет отправителю завершиться, даже если ответ не нужен

А ещё Найти: runtime.NumGoroutine, pprof goroutine-профиль, goleak в тестах

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Почему это серьёзно. Сборщик мусора не освобождает заблокированные горутины — с точки зрения рантайма они живы. В долгоживущем сервисе их число растёт с каждым запросом, а с ними память и открытые соединения.

Правила:

  • запуская горутину, знать, когда и как она завершится;
  • передавать context и проверять ctx.Done() в циклах и select;
  • у внешних вызовов — таймауты (http.Client{Timeout}, context.WithTimeout);
  • закрывать каналы, по которым читают через range;
  • результат «может быть никому не нужен» — канал с буфером 1.

Диагностика: метрика go_goroutines, /debug/pprof/goroutine?debug=1 показывает стеки — тысячи одинаковых стеков указывают на место утечки; go.uber.org/goleak проверяет в тестах, что горутин не осталось.

Пример

// утечка: при таймауте горутина навсегда висит на отправке
func fetch(ctx context.Context) (string, error) {
    ch := make(chan string)
    go func() { ch <- slowCall() }()
    select {
    case r := <-ch:
        return r, nil
    case <-ctx.Done():
        return "", ctx.Err()
    }
}
// исправление: make(chan string, 1) — отправка не заблокируется

Что хотят услышать

  • Что такое утечка и типичные причины.
  • Как предотвращать.
  • Как обнаружить.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем