关于向关闭的channel中发送数据的问题

来源:1-6 Go 语法背后的秘密

Dobby喵

2021-05-21 14:34:36

ch := make(chan int)
close(ch)
ch<-1

问题描述:

曹大代码如上,再用dlv调试的时候我发现上述代码好像一共调用了2次chansend方法,请问这个是什么逻辑呢。

尝试过的解决方式:

自己在顺着源码分析得时候,没能看懂相应得原因

写回答

1回答

Xargin

2021-05-21

程序启动的时候 gc 相关的也有一些 channel 操作,你可以用 dlv 的 bt 命令,看看当前的 chansend 是从哪里进去的,

(dlv) c
> runtime.chansend() /usr/local/go/src/runtime/chan.go:142 (hits goroutine(4):1 total:1) (PC: 0x1004053)
Warning: debugging optimized function
   137:	 * sleep can wake up with g.param == nil
   138:	 * when a channel involved in the sleep has
   139:	 * been closed.  it is easiest to loop and re-run
   140:	 * the operation; we'll see that it's now closed.
   141:	 */
=> 142:	func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
   143:		if c == nil {
   144:			if !block {
   145:				return false
   146:			}
   147:			gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
(dlv) bt
0  0x0000000001004053 in runtime.chansend
   at /usr/local/go/src/runtime/chan.go:142
1  0x0000000001004035 in runtime.chansend1
   at /usr/local/go/src/runtime/chan.go:127
2  0x000000000101c0c3 in runtime.bgscavenge
   at /usr/local/go/src/runtime/mgcscavenge.go:236
3  0x000000000105a941 in runtime.goexit
   at /usr/local/go/src/runtime/asm_amd64.s:1373


你要调试的是 main 里的这一句,所以可以先进 main.main 函数,然后再在 chansend 上打断点,然后按 c(continue)


下面这种有 main.main 的才是你应该注意的操作位置:

(dlv) c
> runtime.chansend() /usr/local/go/src/runtime/chan.go:142 (hits goroutine(1):1 total:3) (PC: 0x1004053)
Warning: debugging optimized function
   137:	 * sleep can wake up with g.param == nil
   138:	 * when a channel involved in the sleep has
   139:	 * been closed.  it is easiest to loop and re-run
   140:	 * the operation; we'll see that it's now closed.
   141:	 */
=> 142:	func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
   143:		if c == nil {
   144:			if !block {
   145:				return false
   146:			}
   147:			gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
(dlv) bt
0  0x0000000001004053 in runtime.chansend
   at /usr/local/go/src/runtime/chan.go:142
1  0x0000000001004035 in runtime.chansend1
   at /usr/local/go/src/runtime/chan.go:127
2  0x000000000105ee13 in main.main
   at ./cs.go:6
3  0x000000000102fdb8 in runtime.main
   at /usr/local/go/src/runtime/proc.go:203
4  0x000000000105a941 in runtime.goexit
   at /usr/local/go/src/runtime/asm_amd64.s:1373


1

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程