Какие существуют состояния у канала (chan) в Go и как они себя ведут?

Ответ

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

  1. nil (нулевой)

    • Это нулевое значение для типа chan. Канал не инициализирован (var ch chan int).
    • Поведение: Любая операция отправки или получения данных на nil-канале заблокирует текущую горутину навсегда. Попытка закрыть nil-канал вызовет панику.
  2. Открытый (open)

    • Канал инициализирован с помощью make() (например, ch := make(chan int)).
    • Поведение: Канал готов к приему и отправке данных. Операции могут блокироваться в зависимости от буферизации канала (небуферизованный блокируется, пока другая сторона не будет готова; буферизованный — пока буфер не заполнится/опустеет).
  3. Закрытый (closed)

    • Канал был закрыт с помощью функции close().
    • Поведение:
      • Отправка данных в закрытый канал вызывает панику.
      • Получение данных из закрытого канала не блокируется, а немедленно возвращает нулевое значение для типа канала и второй параметр ok со значением false.
      • Попытка закрыть уже закрытый канал вызывает панику.

Сводная таблица поведения:

СостояниеЧтение (<-ch)Запись (ch <- val)Закрытие (close(ch))
nilБлокируется навсегдаБлокируется навсегдаПаника
ОткрытыйБлокируется до записи / ЧитаетБлокируется до чтения / ПишетУспешно
Закрытыйzero_value, false (немедленно)ПаникаПаника

Пример проверки:

ch := make(chan int, 1)
ch <- 10
close(ch)

val, ok := <-ch // val = 10, ok = true (читаем из буфера)
val, ok = <-ch // val = 0, ok = false (канал пуст и закрыт)