Go语言Channel发送消息,接收端仅收到隔条消息问题排查
Go通道管道接收端仅收到隔条消息的问题排查与解决
问题根源
你代码中的核心问题出在main函数的通道遍历逻辑上:
for range takeNChan { received := <-takeNChan fmt.Println("main takeNchan: ", received) }
for range遍历通道时,每次迭代会自动从通道读取一个元素,但你在循环体内又额外执行了一次<-takeNChan读取操作。这导致每次循环实际消耗了通道中的两个元素:一个被for range的迭代过程消耗(但未打印),另一个被循环体内的读取语句获取并打印。因此10个元素仅会触发5次循环,最终只打印了5条消息。
修复方案
有两种简单的修复方式:
方案1:使用for range的迭代变量接收值
直接利用for range遍历通道时返回的元素值,无需额外读取:
for received := range takeNChan { fmt.Println("main takeNchan: ", received) }
方案2:使用普通for循环配合通道接收的ok模式
通过判断通道是否关闭来终止循环,避免重复读取:
for { received, ok := <-takeNChan if !ok { // 通道已关闭,退出循环 break } fmt.Println("main takeNchan: ", received) }
补充说明
- 你对goroutine顺序执行、通道发送接收同步的理解是正确的:
takeN中的outputStream <- in确实会阻塞到接收端就绪,fmt.Println("out from takeN: ", in)也确实是发送完成后才执行的。 - 问题并非消息未被接收,而是一半的消息被
for range的迭代过程悄悄消耗,没有被打印出来。即使改用缓冲通道,这个逻辑错误依然存在,因为本质是读取次数的问题,而非通道缓冲特性。
内容的提问来源于stack exchange,提问作者Andrew Pham
相关产品推荐
相关产品推荐

