golang chan 关闭时的原则
(金庆的专栏 2020.1)
golang 程序中检测到 DATA RACE, 是 chan 关闭和发送冲突:
==================
WARNING: DATA RACE
Write at 0x00c000098010 by goroutine 68:
runtime.closechan()
/usr/lib/golang/src/runtime/chan.go:327 +0x0
valky/common/tcp.(*Session).Close()
/var/tmp/src/f4f4f712-7894-4d98-83dd...
valky/common/tcp.(*Session).recvloop()
/var/tmp/src/f4f4f712-7894-4d98-83dd...
Previous read at 0x00c000098010 by goroutine 100:
runtime.chansend()
/usr/lib/golang/src/runtime/chan.go:140 +0x0
valky/common/tcp.(*Session).Send()
/var/tmp/src/f4f4f712-7894-4d98-83dd...
main.(*Role).sendMsg()
/var/tmp/src/f4f4f712-7894-4d98-83dd...
==================
Found 1 data race(s)
查了一下 chan 关闭的正确做法,发现了一篇非常详细的文章:
[How to Gracefully Close Channels](https://go101.org/article/channel-closing.html)
文中指出,chan 多次关闭,或者在关闭的 chan 上发送,都会 panic.
上面的 DATA RACE 属于幸运,没有 panic。
chan 关闭时的原则是:不要在接收协程中关闭,并且,如果有多个发送者时就不要关闭chan了。
上面的DATA RACE 是在接收协程中关闭chan.
文中详细列出了多种方案关闭chan.
如果粗暴点,可以直接加个 recover. 其他方案都是要保证发送完成后再关闭。