Какие операции допустимы с закрытым каналом в Go и каково его поведение?

Ответ

С закрытым каналом в Go можно выполнять ограниченный набор операций, в основном связанных с чтением. Поведение канала после закрытия предсказуемо и является важной частью механики конкурентности в Go.

Допустимые операции

  1. Чтение из канала.
    • Если в буфере канала остались значения, они будут успешно прочитаны одно за другим.
    • Когда буфер опустеет, любая операция чтения немедленно вернет нулевое значение для типа данных канала и false в качестве второго параметра (value, ok := <-ch). Это позволяет понять, что канал закрыт и данных больше не будет.
  2. Использование в цикле for range.
    • Цикл for v := range ch будет итерироваться по всем оставшимся в буфере значениям. После того как все значения будут прочитаны, цикл корректно завершится, не вызывая блокировки или паники. Это основной способ для graceful shutdown воркеров.

Запрещенные операции (вызывают панику)

  1. Запись в закрытый канал.
    • Попытка отправить значение в закрытый канал (ch <- data) немедленно вызовет панику: panic: send on closed channel.
  2. Повторное закрытие канала.
    • Попытка закрыть уже закрытый канал (close(ch)) также вызовет панику: panic: close of closed channel.

Пример

package main

import "fmt"

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    close(ch) // Закрываем канал

    // Читаем оставшиеся значения
    val, ok := <-ch
    fmt.Printf("Прочитано: %d, канал открыт: %vn", val, ok) // Прочитано: 1, канал открыт: true

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

    // Канал пуст и закрыт
    val, ok = <-ch
    fmt.Printf("Прочитано: %d, канал открыт: %vn", val, ok) // Прочитано: 0, канал открыт: false
}

Основные сценарии использования

  • Сигнализация о завершении: Горутина-продюсер закрывает канал, чтобы сообщить горутинам-консьюмерам, что работа завершена и новых данных не будет.
  • Трансляция сигнала нескольким горутинам: Закрытие канала done может быть использовано для одновременного оповещения множества горутин о необходимости завершить свою работу.