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

为何向通道发送奇数个整数时Go程序才正常运行?

为什么Go程序仅在发送奇数个值到通道时才正常打印所有内容?

哇,这个现象确实有点让人摸不着头脑,我来帮你拆解下背后的逻辑——其实这和奇数/偶数本身没有直接关系,完全是Go程序的协程调度和生命周期规则导致的巧合。

首先先看你提供的代码:

package main
import "fmt"
func main() {
    ch := make(chan int)
    go Print(ch)
    for i := 1; i <= 12; i++ {
        ch <- i
    }
    close(ch)
}
func Print(ch <-chan int) {
    for n := range ch{
        fmt.Println(n)
    }
}

核心问题:main函数退出会终止所有协程

Go程序的运行规则是:一旦main函数执行完毕,整个程序就会立刻终止,所有正在后台运行的协程都会被强制停止,不管它们有没有完成任务。

在你的代码里,main函数做完这几件事就会退出:

  1. 启动Print协程
  2. 把1到12(偶数个)全部发送到通道
  3. 关闭通道

问题就出在这里:close(ch)执行后,main函数没有等待Print协程把通道里的所有值都处理完,就直接结束了。这时候Print协程可能还在处理通道里的剩余值,就被程序终止了,导致部分值没打印出来。

为什么奇数个值的时候看起来“正常”?

这纯粹是Go调度器的随机巧合。当你发送奇数个值时,最后一次ch <- i执行后,main函数执行close(ch)的瞬间,调度器可能刚好切换到Print协程,让它把剩下的所有值都打印完;而发送偶数个值时,main函数可能在调度器切换到Print协程之前就已经退出了,导致部分值来不及打印。

这种行为是不确定的——你多跑几次代码,哪怕是发送奇数个值,也有可能出现打印不全的情况,只是概率更低而已,并不是奇数个值有什么特殊的“魔法”。

补充:如何确保所有值都被打印(仅作知识补充,不是作业解答)

如果你想让程序稳定地打印所有值,本质上是要让main函数等待Print协程完成任务。比如可以用sync.WaitGroup:

package main
import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

func main() {
    ch := make(chan int)
    wg.Add(1)
    go Print(ch)
    for i := 1; i <= 12; i++ {
        ch <- i
    }
    close(ch)
    wg.Wait() // 等待Print协程完成
}

func Print(ch <-chan int) {
    defer wg.Done()
    for n := range ch {
        fmt.Println(n)
    }
}

不过你提到不需要作业解决方案,所以重点还是理解前面说的调度巧合和协程生命周期规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:40:53