Why does Go panic on writing to a closed channel?
While one can use the value, ok := <-channel
idiom for reading from channels, and thus the ok result can be tested for hitting a closed channel:
// reading from closed channel
package main
import "fmt"
func main() {
ch := make(chan int, 1)
ch <- 2
close(ch)
read(ch)
read(ch)
read(ch)
}
func read(ch <-chan int) {
i,ok := <- ch
if !ok {
fmt.Printf("channel is closed\n")
return
}
fmt.Printf("read %d from channel\n", i)
}
Output:
read 2 from channel
channel is closed
channel is closed
Run "reading from closed channel" on Playground
Writing to a possibly closed channel is more convoluted, because Go will panic if you simply try to write when the channel is closed:
//writing to closed channel
package main
import (
"fmt"
)
func main() {
output := make(chan int, 1) // create channel
write(output, 2)
close(output) // close channel
write(output, 3)
write(output, 4)
}
// how to write on possibly closed channel
func write(out chan int, i int) (err error) {
defer func() {
// recover from panic caused by writing to a closed channel
if r := recover(); r != nil {
err = fmt.Errorf("%v", r)
fmt.Printf("write: error writing %d on channel: %v\n", i, err)
return
}
fmt.Printf("write: wrote %d on channel\n", i)
}()
out <- i // write on possibly closed channel
return err
}
Output:
write: wrote 2 on channel
write: error writing 3 on channel: send on closed channel
write: error writing 4 on channel: send on closed channel
Run "writing to closed channel" on Playground
As far as I know, there is not a simpler idiom for writing into a possibly closed channel without panicking. Why not? What is the reasoning behind such an asymmetric behavior between read and write?