channel关闭后出现写入问题
目录
channel关闭后出现写入问题
0 前言
本文代码基于golang 1.19进行讲解(水平有限,共同探讨,不足之处欢迎指正)
1 问题
今天面试遇到一道channel
相关的问题,感觉自己一下在脑袋空白了,什么思路都没有想起来,特此记录一下。
问题:假设有一个Web Server,使用到了channel,并且在一个函数内传递了这个channel,进行往channel中发送数据的操作,并且在函数外部关闭了channel,如何知道channel关闭了,并且使函数内往channel操作不panic。具体表现如下:
|
|
以上可以看出,当往关闭的channel继续发送数据会出现panic,所以该怎么解决呢?
2 解决办法
2.1 使用 select 检查 channel 是否可用(非阻塞)
|
|
这种方式无法明确知道 channel 是“已关闭”还是“满了”,只能判断是否可以立即写入。而且会出现,channel未关闭,但是函数直接返回的情况
2.2 用额外的 done channel 或 context 控制生命周期
|
|
这样你就不会冒险向一个关闭的 channel 写入数据,你也可以把context换成done channel,效果是一样的(这样我感觉会不会还有坑,希望各位大佬指正)
3 总结
Go 中 关闭一个 channel 后再次向其发送数据会触发 panic 。因此最佳实践是:
- 只由发送者关闭 channel (生产者负责关闭)
- 接收者不关闭 channel
- 如果你在多个 goroutine 中写入同一个 channel,那么不能随意关闭它,否则可能导致 panic
只要记住:
don’t close a channel from the receiver side and don’t close a channel if the channel has multiple concurrent senders.
更本质的原则:
don’t close (or send values to) closed channels.