MiddleКодЧастоЕщё не отвечали
Приём из закрытого channel, отправка в него и повторное закрытие — предскажите каждую
Для каждой из трёх пронумерованных строк укажите, что именно произойдёт во время выполнения (возвращённое значение, блокировка или panic с его сообщением), и объясните почему.
ch := make(chan int, 1)
close(ch)
v, ok := <-ch // (1)
ch <- 1 // (2)
close(ch) // (3)
Предскажите исход каждой строки.
Приём из закрытого channel возвращает нулевое значение с ok == false, поэтому (1) даёт v == 0, ok == false. Отправка в закрытый channel паникует с send on closed channel, поэтому (2) паникует. Повторное закрытие закрытого channel тоже паникует, поэтому (3) паникует. Правило — закрывает отправитель, никогда не получатель, и только один раз.
- ✗Думать, что приём из закрытого channel блокируется, а не возвращает нулевое значение с
ok == false - ✗Считать, что закрытый channel всё ещё принимает отправки — он паникует
- ✗Полагать, что
closeидемпотентен — повторное закрытие паникует
- →Как безопасно скоординировать закрытие, когда отправителей несколько?
- →Почему
rangeпо закрытому channel завершается чисто, а одиночный приём возвращает нули бесконечно?
Оглавление
Предскажите каждую строку
ch := make(chan int, 1)
close(ch)
v, ok := <-ch // (1)
ch <- 1 // (2)
close(ch) // (3)
Результат
(1) v == 0, ok == false // приём из закрытого канала
(2) panic: send on closed channel
(3) panic: close of closed channel // если бы дошли сюда
Правила закрытого channel
- (1) Приём из закрытого channel не блокируется: он отдаёт все буферизованные значения, а затем — нулевое значение типа с
ok == false. Здесь буфер пуст, поэтому сразу0, false. Именно такrangeпонимает, что пора завершаться. - (2) Отправка в закрытый channel всегда паникует:
send on closed channel. Закрытие — это сигнал «значений больше не будет», поэтому новые отправки запрещены. - (3) Повторное закрытие тоже паникует:
close of closed channel. (Программа уже упала бы на строке 2 — но сама по себе строка 3 панует.)
⚠️ Правило: закрывать должен отправитель, ровно один раз. Получатель никогда не закрывает; при нескольких отправителях координируйте закрытие через отдельную горутину-владельца или sync.Once.
Оглавление