Чтение из открытого пустого канала ожидает отправку. Если закрытый канал уже опустошён, чтение немедленно вернёт нулевое значение и ok=false. Чтение из nil-канала блокируется навсегда. Обычно приостанавливается текущая горутина, а не весь поток ОС; другие горутины могут продолжать работу.
Блокирует ли чтение из пустого канала выполнение в Go?
Открытый, закрытый и nil-канал ведут себя по-разному. Блокируется горутина; select позволяет добавить отмену или неблокирующую ветку.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Нужно уточнить состояние канала. Пустота буфера сама по себе не описывает все случаи:
- Открытый канал без доступного значения: чтение ждёт отправителя.
- Закрытый канал с буфером: сначала читаются сохранённые значения.
- Закрытый и опустошённый канал: немедленно возвращаются нулевое значение типа и
ok == false. - nil-канал: обычное чтение не завершается.
Пример закрытого канала:
ch := make(chan int, 1)
ch <- 42
close(ch)
value, ok := <-ch // 42, true
value, ok = <-ch // 0, false
_ = value
_ = ok
Правила приведены в спецификации Go. Нулевое значение не доказывает закрытие: отправитель тоже может передать 0, поэтому используют форму с ok.
При ожидании канал приостанавливает текущую горутину; рантайм может выполнять другие горутины на доступных потоках. Это не остановка всей программы. Если все возможные участники ждут и никто не сможет отправить, программа может оказаться в deadlock.
В select можно предусмотреть ctx.Done() для отмены или default для неблокирующей попытки. Но цикл с постоянно выбираемым default способен бесполезно расходовать CPU.