Что произойдет при попытке записи в закрытый канал (channel) в Go?

Ответ

При попытке записи в закрытый канал в Go произойдет паника (panic).

Это сделано намеренно, чтобы предотвратить ошибки, когда отправитель пытается отправить данные в канал, который получатели уже не слушают. Такое поведение сигнализирует о серьезной ошибке в логике программы.

Пример:

package main

import "fmt"

func main() {
    ch := make(chan int, 1)
    close(ch)

    // Эта строка вызовет панику
    // panic: send on closed channel
    ch <- 42 
    fmt.Println("Это сообщение не будет выведено")
}

Ключевые моменты:

  1. Паника при записи: Запись в закрытый канал — это всегда паника.
  2. Чтение возможно: Чтение из закрытого канала панику не вызывает (см. отдельный вопрос).
  3. Паника при повторном закрытии: Попытка закрыть уже закрытый канал также вызывает панику (panic: close of closed channel).
  4. Кто закрывает канал? По общепринятому соглашению, канал должен закрывать только отправитель. Если у канала несколько отправителей, закрывать его должен тот, кто координирует их работу, или после того, как все отправители завершат свою работу (например, с помощью sync.WaitGroup).

Ответ 18+ 🔞

Так, слушай, вот тебе история про каналы в Go, которая может закончиться пиздецом, если не знать правил. Представь себе, что канал — это такая труба, по которой ты кидаешь данные. И вот ты её закрыл, типа "всё, ребята, я закончил, больше ничего не будет". А потом, через минуту, пытаешься сунуть в эту закрытую трубу ещё один кирпич. Что произойдёт? Правильно, программа твоя встанет в позу и начнёт орать паникой.

Это не баг, это фича, ёпта! Так сделано специально, чтобы твоя криворукая логика не проебала всё к чертям. Чтобы ты сразу понял, что пытаешься отправить данные туда, куда их уже никто не ждёт.

Смотри, как это выглядит в коде:

package main

import "fmt"

func main() {
    ch := make(chan int, 1) // Сделал трубу, в неё можно один кирпич положить
    close(ch) // Закрыл её нахуй, типа всё

    // А теперь попробуй сунуть туда число 42...
    // И тут же: ПАНИКА, БЛЯДЬ! send on closed channel
    ch <- 42
    fmt.Println("До этой строчки мы никогда не доживём, ядрёна вошь")
}

Коротко о главном, чтобы не облажаться:

  1. Запись в закрытый канал = гарантированная паника. Это как пытаться накормить мёртвого голубя — хуй ты что добьёшься, кроме чувства брезгливости.
  2. Чтение из закрытого — можно. Там уже лежащее заберёшь, а потом будешь получать нули (это отдельная тема, но паники не будет).
  3. Двойное закрытие — тоже паника. Закрыл канал второй раз? panic: close of closed channel. Сам дурак.
  4. Кто хозяин, тот и закрывает. По неписаному закону джунглей, закрывать канал должен тот, кто в него пишет. Если писателей много, то нужно договориться, кто последний выйдет и выключит свет. Обычно для этого используют sync.WaitGroup, чтобы все закончили, а потом уже — бац, и закрыл. Иначе будет бардак, волнение ебать, и все начнут кидаться паниками друг в друга.