Ответ
Поведение при чтении из закрытого и nil
-канала кардинально отличается и является важной концепцией для понимания конкурентности в Go.
Чтение из закрытого канала
Чтение из закрытого канала никогда не блокируется. Оно немедленно возвращает два значения:
- Zero-value для типа данных канала.
false
в качестве второго параметра (ok
).
Это позволяет надежно определить, что канал был закрыт и больше не будет поставлять данные.
ch := make(chan int, 1)
ch <- 100
close(ch)
val, ok := <-ch // val = 100, ok = true (читаем последнее значение)
val, ok = <-ch // val = 0, ok = false (канал пуст и закрыт)
val, ok = <-ch // val = 0, ok = false (можно читать бесконечно)
Чтение из nil
-канала
Канал является nil
, если он был объявлен, но не инициализирован с помощью make()
.
Чтение из nil
-канала блокирует горутину навсегда. Это приводит к deadlock, если ни одна другая горутина не сможет записать в этот канал (что невозможно, так как он nil
).
var ch chan int // ch == nil
// Эта операция заблокирует текущую горутину навсегда
// и программа упадет с паникой deadlock
<-ch
Сводная таблица поведения
Операция | Закрытый канал | nil -канал |
---|---|---|
Чтение (<-ch ) | Немедленно возвращает (zero-value, false) | Блокирует навсегда (deadlock) |
Запись (ch <- val ) | Паника (panic) | Блокирует навсегда (deadlock) |
Закрытие (close(ch) ) | Паника (panic on second close) | Паника (panic) |