Что происходит при записи или чтении из закрытого канала в Go
Что проверяют
Знаете ли вы точное поведение в каждом случае. Это конкретный вопрос, где ценится точность, а не рассуждение.
Как отвечать
По случаям:
- чтение из закрытого канала: возвращается немедленно, отдавая нулевое значение типа. Отличить это от настоящего значения позволяет вторая переменная:
v, ok := <-ch, гдеok == falseозначает, что канал закрыт и опустошён. Буферизованный канал сначала отдаёт всё, что в нём лежало, и только потом начинает возвращать нули; - запись в закрытый канал: паника
send on closed channel. Восстановиться из неё в общем случае нельзя и не нужно, это ошибка проектирования; - повторное закрытие: тоже паника,
close of closed channel; - закрытие нулевого канала: паника. А чтение и запись в нулевой канал (
var ch chan int) блокируются навсегда, что иногда используют осознанно, чтобы отключить ветку вselect; - range по каналу: цикл сам завершается, когда канал закрыт и опустошён.
Отсюда правило, которое и хотят услышать: закрывает канал отправитель, и только он. Получатель закрывать не должен, потому что не знает, будет ли ещё запись. Когда отправителей несколько, канал закрывают после того, как все они закончили, обычно через sync.WaitGroup и отдельную горутину с close.
Закрытие это не освобождение ресурса, а сигнал «данных больше не будет». Не закрывать канал нормально, если приём завершается иначе.
Где спотыкаются
Закрывают канал в получателе.
Не проверяют второе значение и обрабатывают нули как настоящие данные.
Закрывают канал из нескольких горутин и ловят панику.
Считают, что закрытие обязательно, иначе будет утечка.