【发布时间】:2016-04-26 04:03:27
【问题描述】:
为什么 Go 在写入已关闭的频道时会出现恐慌?
虽然可以使用value, ok := <-channel 习惯用法从通道中读取,因此可以测试 ok 的结果是否命中已关闭的通道:
// 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)
}
输出:
read 2 from channel
channel is closed
channel is closed
在Playground上运行“从封闭通道读取”
写入可能已关闭的通道更加复杂,因为如果您只是在通道关闭时尝试写入,Go 会出现恐慌:
//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
}
输出:
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
在Playground上运行“写入封闭通道”
据我所知,没有更简单的习惯用法可以在不恐慌的情况下写入可能已关闭的频道。为什么不?读写之间的这种不对称行为背后的原因是什么?
【问题讨论】:
-
我们怎么知道?在 google golang group 上提问,也许其中一位作者会回答你。我能想到一个原因。在生产者端关闭频道只是一个很好的设计。恐慌迫使您以这种方式设计您的应用程序。
-
关闭通道是一个信号,这里将不再有值。写入已关闭的通道是程序错误,会出现恐慌。
标签: go concurrency channel goroutine panic