Ответ
Каналы в Go могут находиться в одном из трёх состояний, каждое из которых имеет свои особенности поведения при операциях чтения, записи и закрытия.
nil
(нулевой)- Это нулевое значение для типа
chan
. Канал не инициализирован (var ch chan int
). - Поведение: Любая операция отправки или получения данных на
nil
-канале заблокирует текущую горутину навсегда. Попытка закрытьnil
-канал вызовет панику.
- Это нулевое значение для типа
Открытый (open)
- Канал инициализирован с помощью
make()
(например,ch := make(chan int)
). - Поведение: Канал готов к приему и отправке данных. Операции могут блокироваться в зависимости от буферизации канала (небуферизованный блокируется, пока другая сторона не будет готова; буферизованный — пока буфер не заполнится/опустеет).
- Канал инициализирован с помощью
Закрытый (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 (канал пуст и закрыт)