You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Go语言Channel未取到最后一次写入的值?

Go Channel读取结果异常原因分析

问题场景

你在学习Go Channel时遇到了一个奇怪的现象:向带缓冲容量3的Channel写入1到10后,关闭Channel,最后在main函数中额外读取一次Channel,得到的总是倒数第二个写入的值(比如写入10时得到8,写入8时得到6)。你的代码如下:

func main() {
    channel := make(chan int, 3)
    isOver := make(chan bool)

    go func() {
        for val := range channel {
            fmt.Println(val)
        }
        isOver <- true
    }()

    channel <- 1
    channel <- 2
    channel <- 3
    channel <- 4
    channel <- 5
    channel <- 6
    channel <- 7
    channel <- 8
    channel <- 9
    channel <- 10
    close(channel)

    fmt.Println("Channel Value is: ", <-channel)

    <-isOver
}

原因解释

核心问题出在main函数的额外读取操作和带缓冲Channel的阻塞特性上,具体流程如下:

  1. 你的Channel缓冲容量为3,main函数顺序写入值时,每当缓冲被占满,写入操作会阻塞,直到后台goroutine读取一个值释放出缓冲空间,main才能继续写入下一个值。
  2. 当main写完最后一个值(比如10)时,Channel缓冲里恰好剩下3个未被goroutine读取的值:[8,9,10]。
  3. main关闭Channel后,立刻执行了<-channel操作,抢先读取了缓冲里的第一个值(8)。
  4. 之后后台goroutine才继续读取剩下的9和10并打印,因此你会看到goroutine的输出里没有8,而main的打印结果是8。

当你把最后一次写入的值改成8时,写完后缓冲里剩下的是[6,7,8],main抢先读取第一个值6,goroutine后续读取7和8,所以结果变成6,逻辑完全一致。

解决建议

如果希望goroutine读取所有写入Channel的值,只需要移除main函数中那行额外的<-channel读取操作即可:

// 删掉这一行
// fmt.Println("Channel Value is: ", <-channel)

内容的提问来源于stack exchange,提问作者KaganBerk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:14:51