Why does Go panic when recording to a private channel?

Why does Go panic when recording to a private channel?

Although you can use the idiom value, ok := <-channel to read from channels, and thus, the result of ok can be tested to get into 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 

Launch "reading from the closed channel" on the Playground

Recording to a possibly closed channel is more confusing because Go will panic if you just try to record 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 

Launch a “private channel entry” on the Playground

As far as I know, there is no simpler idiom for recording into a possibly closed channel without panic. Why not? What is the reason for this asymmetric behavior between reading and writing?

+8
concurrency go panic goroutine channel
source share
1 answer

From Go Language Spec :

For channel c, the built-in close (c) function records that no more than values ​​will be sent on the channel. This is an error if c is a receive-only channel. Sending or closing a closed channel causes a temporary panic. Closing the nil channel also causes run-time panic. After calling close and after all previously sent values ​​have been received, the received operations return a zero value for the channel type without blocking. A multi-valued receive operation returns the received value along with an indication of whether the channel is closed.

If you write to a private channel, your program will panic. You could potentially catch this error during recovery if you really want to do it, but being in a situation where you do not know if your channel will be written to open, is usually a sign of an error in the program.

Some quotes:

Here is the motivation:

The close channel is actually just sending a special value to the channel. Of particular importance is the promises that no more values ​​will be sent. Attempting to send a value on the channel after it was closed will panic, since the actual sending of the value will violate the guarantee provided by the closing. Since closing is just a special kind of Submit, it is also not allowed after closing the channel.

Here is another one:

The only use of channel closure is to signal to the reader that they are no longer coming. This only makes sense when there is one source of values, or when several sources are coordinated. There is no reasonable program in which several gorutov close the channel without communication. This would mean that many goroutines would know that there are no more values ​​to send — how could they determine if they weren’t communicating?

(Ian Lance Taylor)

-

Here is another one:

Closing a channel frees it as a resource. It makes no sense to close the channel several times than it does to close the file descriptor several times or a free block of allocated memory many times. Such actions imply that the code is broken, so closing a closed channel causes panic.

(Rob Pike)

-

Source: Go to the Design Details Question - Direct Channel

+11
source share

All Articles