Вопрос с собеседования · 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 минут бесплатно.