douyi6818 2016-01-20 10:45
浏览 38


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


func read(ch <-chan int) {
    i,ok := <- ch   
    if !ok {
        fmt.Printf("channel is closed
    fmt.Printf("read %d from channel
", i)


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 (

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
", i, err)

        fmt.Printf("write: wrote %d on channel
", i)

    out <- i // write on possibly closed channel

    return err


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?

  • 写回答

1条回答 默认 最新

  • dongzhi6905 2016-01-20 11:43

    From the Go Language Spec:

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

    If you write to a closed channel, your program will panic. You could potentially catch this error with recover if you really want to do that, but being in a situation where you don't know whether the channel you are writing to is open is usually a sign of a bug in the program.

    Some quotes:

    Here is a motivation:

    A channel "close" is really just a send of a special value on a channel. It is a special value that promises that no more values will be sent. Attempting to send a value on a channel after it has been closed will panic, since actually sending the value would violate the guarantee provided by close. Since a close is just a special kind of send, it is also not permitted after the channel has been closed.

    Here is another:

    The only use of channel close is to signal to the reader that there are no more values to come. That only makes sense when there is a single source of values, or when multiple sources coordinate. There is no reasonable program in which multiple goroutines close a channel without communicating. That would imply that multiple goroutines would know that there are no more values to send--how could they determine that if they don't communicate?

    (Ian Lance Taylor)


    Here is another:

    Closing a channel releases it as a resource. It makes no more sense to close a channel multiple times than it makes to close a file descriptor multiple times, or free a block of allocated memory multiple times. Such actions imply the code is broken, which is why closing a closed channel triggers a panic.

    (Rob Pike)


    Source: Go design detail rationale question - channel close

    本回答被题主选为最佳回答 , 对您是否有帮助呢?



    • ¥15 大一Python字典
    • ¥15 multisim电路设计(相关搜索:设计报告)
    • ¥15 从github上下载的项目到ecplise上咋运行
    • ¥15 PC-lint Plus
    • ¥15 gpl24676注释
    • ¥15 php5.3内存泄露
    • ¥15 DigSilent如何复制复合模型到自己案例?
    • ¥15 求日版华为b610s-77a 官方公版固件,有偿
    • ¥15 关于#java#的问题,请各位专家解答!(相关搜索:java程序)
    • ¥15 linux tsi721的驱动编译后 insmod 提示 报错