Вступить в клуб →
сложнаявопросКонкурентность: горутины, каналы, context

Утечка горутин при выходе по таймауту из select

Обёртка над медленным поиском написана так:

func Search(ctx context.Context, q string) (Result, error) {
    ch := make(chan Result)

    go func() {
        ch <- slowSearch(q) // без учёта ctx
    }()

    select {
    case r := <-ch:
        return r, nil
    case <-ctx.Done():
        return Result{}, ctx.Err()
    }
}

После деградации поискового бэкенда график go_goroutines растёт линейно и не падает. Что произошло?

  • Горутина завершается вместе с `Search`, а рост горутин вызван самим `select`
  • Проблемы нет: `slowSearch` получит отмену через контекст и вернёт управление
  • Сборщик мусора соберёт заблокированные горутины, растёт лишь показания метрики
  • При срабатывании `ctx.Done()` горутина навсегда виснет на `ch <- ...`; помогает буфер размером 1

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела