Вопрос с собеседования · Go

Как работает select в Go?

JuniorГорутины и каналы
Ещё спрашивают так:
  • Как сделать таймаут при чтении из канала?
Коротко

select ждёт сразу несколько операций с каналами и выполняет ту, что готова первой; если готовы несколько — случайную. Ветка default делает select неблокирующим. Таймаут — ветка <-time.After(d) или <-ctx.Done().

  • Пустой select{} блокирует навсегда
  • nil-канал в select никогда не готов — так «выключают» ветку
  • Случайный выбор предотвращает голодание одного канала

А ещё time.After в цикле создаёт таймер на каждой итерации — лучше time.NewTimer или context

Подробно

Типичные шаблоны:

  • таймаут — ветка с таймером или контекстом;
  • отмена — <-ctx.Done() в каждом цикле обработки;
  • неблокирующая попытка — default;
  • слияние нескольких источников — несколько case на получение;
  • отключение ветки — присвоить каналу nil, когда он закрыт.

Select выбирает среди готовых случайно — нельзя полагаться на порядок веток как на приоритет. Приоритет делают вложенными select.

Пример

select {
case msg := <-messages:
    handle(msg)
case <-ctx.Done():
    return ctx.Err()
case <-time.After(2 * time.Second):
    return errors.New("таймаут")
}

select {                 // неблокирующая отправка
case events <- e:
default:
    dropped++
}

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

  • Выбор готовой операции, случайность.
  • default и таймауты.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗select выполняет все готовые ветки по порядку
  • ✗nil-канал в select всегда готов
  • ✓Ждёт операции с каналами; из готовых выбирает случайную
  • ✗Ждёт операции с каналами; из нескольких готовых всегда берёт первую по тексту

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

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования