Как в Go проверить, что канал закрыт?

Ответ

В Go для проверки состояния канала используется вторая переменная, возвращаемая при операции чтения. Это идиоматичный и основной способ.

1. Проверка при чтении

При чтении из канала можно получить два значения: само значение и флаг ok (boolean).

value, ok := <-ch
  • Если ok равно true, канал открыт и value содержит успешно прочитанное значение.
  • Если ok равно false, канал закрыт. При этом value будет содержать нулевое значение для типа данных канала (например, 0 для int, "" для string, nil для указателей).
ch := make(chan int, 1)
ch <- 10
close(ch)

v, ok := <-ch
fmt.Printf("Прочитано: %d, канал открыт: %vn", v, ok) // Прочитано: 10, канал открыт: true

v, ok = <-ch
fmt.Printf("Прочитано: %d, канал открыт: %vn", v, ok) // Прочитано: 0, канал открыт: false

2. Использование цикла for range

Цикл for v := range ch автоматически прекращает работу, когда канал закрывается и все значения из него прочитаны. Это самый удобный способ читать все данные из канала до его закрытия.

for value := range ch {
    // Этот код выполняется для каждого значения в канале
    fmt.Println("Получено:", value)
}
// Цикл завершится, когда канал 'ch' будет закрыт и опустошен.
// Здесь мы знаем, что канал точно закрыт.

Важное замечание

  • Запись в закрытый канал вызывает панику. Проверить канал на закрытие перед записью невозможно напрямую. Координировать закрытие канала должна та горутина, которая в него пишет (или используется специальный сигнальный канал).