Go语言通道遍历错误引发死锁与异常输出0的原因咨询
Go语言通道遍历错误引发死锁与异常输出0的原因咨询
咱们来一步步拆解你遇到的这两个问题,都是非常典型的Go通道用法误区哦~
一、为什么会输出“received 0”?
你写的for val := range <-bChan这行代码,本质上是先执行<-bChan从通道读取一个值,但这个值是int类型,而Go的range关键字只能作用于数组、切片、map、通道或字符串,根本不能直接作用于单个整数。
那为啥会输出0呢?其实这行代码在语法上就是错的,正常编译器会直接报错,但你的代码意外运行后出现的这个结果,属于非法用法导致的未定义行为。大概率是某次通道读取操作返回了int类型的零值0(比如通道关闭后读取会返回对应类型的零值),然后错误的range逻辑把这个零值当成了可遍历对象,最终就输出了“received 0”。
二、为什么会发生死锁?
咱们梳理下原代码的执行流程,你就懂了:
- main函数先创建了容量为2的缓冲通道,写入1和2之后,通道已经被填满了。
- 启动receiver协程后,main尝试往通道里写3,但通道已满,main会直接阻塞在
bChan <-3这行,必须等通道腾出空间才能继续。 - 但你的receiver协程里的错误代码根本没有在“持续读取通道”:
for val := range <-bChan要么因为语法问题直接终止循环,要么只执行了一次非法操作就退出了,完全没起到清空通道的作用。 - 这下就僵住了:main一直卡着等通道有空位,receiver协程要么已经退出要么卡着不动,所有协程都陷入了互相等待的状态,Go运行时就会触发死锁错误。
而当你改成for val := range bChan后,这个循环会持续从通道里读取值,直到通道被关闭——它会依次把1、2、3、4都读出来,然后执行wg.Done(),main也能顺利写完数据、关闭通道,自然就不会死锁啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

