Управление таймерами и контекстами в Go

Главная проблема — ожидание через Sleep вместо подтверждения завершения горутин. Для явного управления таймером используйте NewTimer и Stop, а для ожидания — WaitGroup.

Короткий ответ

Что ответить на собеседовании

Главная проблема — ожидание через Sleep вместо подтверждения завершения горутин. Для явного управления таймером используйте NewTimer и Stop, а для ожидания — WaitGroup.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо проанализировать представленный код и устранить возможные проблемы, связанные с утечкой ресурсов или незавершёнными таймерами.

func main() {
  ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)

  for i := 0; i < 10; i++ {
    go doRequest(ctx)
  }

  time.Sleep(time.Second)
  cancel()
  time.Sleep(time.Second * 2)
}

func doRequest(ctx context.Context) {
  select {
  case <-time.After(time.Second * 2):
    fmt.Println("timer timeout")
  case <-ctx.Done():
    fmt.Println("context cancelled")
  }
}

Ответ

Главная проблема — ожидание через Sleep вместо подтверждения завершения горутин. Для явного управления таймером используйте NewTimer и Stop, а для ожидания — WaitGroup.

В doRequest создайте timer := time.NewTimer(2*time.Second), отложите timer.Stop() и выбирайте между timer.C и ctx.Done(). В main вызовите wg.Add до запуска каждой горутины, внутри defer wg.Done; после cancel выполните wg.Wait, убрав второй Sleep. Первый Sleep может остаться только как демонстрация отмены через секунду. Начиная с новых правил таймеров Go 1.23 недостижимый time.After может собираться GC, поэтому называть этот пример вечной утечкой во всех версиях неверно.

Источник: go.dev.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее