Вопрос проверяет понимание состояний каналов в Go и поведения при чтении из закрытого канала.
Канал в Go — это типизированный механизм для передачи данных между горутинами. Он может находиться в одном из трех состояний: nil, открытый (активный) и закрытый. Понимание этих состояний критически важно для написания безопасного конкурентного кода.
Канал, объявленный без инициализации (var ch chan int), имеет значение nil. Чтение из nil канала блокирует горутину навсегда, что приводит к утечке горутины. Запись в nil канал также блокируется навсегда. Это свойство иногда используется для отключения ветвей в select.
Открытый канал создается с помощью make(chan int). Чтение из него блокируется, пока нет данных, и успешно извлекает значение, когда данные появляются. Запись блокируется, пока буфер не заполнен (для буферизированных) или пока не появится читатель (для небуферизированных).
Канал закрывается с помощью close(ch). После закрытия запись в канал вызывает панику. Чтение из закрытого канала немедленно возвращает нулевое значение типа элемента. Если использовать форму с двумя возвращаемыми значениями (value, ok := <-ch), то ok будет false, что позволяет отличить закрытый канал от пустого открытого.
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
close(ch)
// Чтение из закрытого канала
for i := 0; i < 5; i++ {
val, ok := <-ch
fmt.Printf("val=%d, ok=%t\n", val, ok)
}
// Вывод:
// val=1, ok=true
// val=2, ok=true
// val=0, ok=false
// val=0, ok=false
// val=0, ok=false
}Закрытие канала используется для сигнализации горутинам о завершении работы. Например, можно закрыть канал, чтобы разблокировать несколько горутин, ожидающих в select. Также это позволяет безопасно завершать циклы range по каналу, так как range автоматически завершается при закрытии канала.
Вывод: знание состояний каналов помогает избежать паник и утечек горутин. Закрытие канала — это механизм сигнализации, а не очистки данных. Используйте close() только когда уверены, что никто больше не будет писать в канал, и для передачи сигнала о завершении.