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

为什么Go语言goroutine通常在for循环执行完毕后才开始运行?

Go循环中goroutine执行时机问题解答

核心问题结论

首先,你听到的「for循环通常比goroutine执行速度更快」的说法是符合绝大多数运行场景的事实,但本质不是二者运行速度的差异,而是Go的goroutine调度机制决定的。

底层原理说明

调度时机的核心规则

你执行go func() {}()语句时,仅仅是向Go运行时的本地goroutine队列提交了一个待调度的任务,并不会立刻中断当前正在运行的主goroutine(也就是执行for循环的goroutine)。只有当前运行的goroutine触发了调度点时,Go调度器才会回收它的执行权,调度其他等待的goroutine运行。
常见的调度点包括系统调用、channel读写、time.Sleep调用、运行栈扩容等,你给出的两段示例代码中,for循环全程没有任何调度点触发,所以主goroutine会连续跑完所有循环迭代,直到执行到最后的time.Sleep语句时才会让出CPU,这时候之前提交的所有goroutine才会被调度执行。

第二段代码的输出原因解释

你在循环内声明的ii := i确实是每次迭代都会新建的独立变量,但你提交goroutine之后立刻对当前迭代的ii赋值为10,而所有goroutine都是在整个循环结束后才开始执行的,此时每个闭包捕获的对应迭代的ii变量早就已经被修改为10,所以最终所有goroutine都会输出10。

正确写法参考

如果要让goroutine拿到提交时的变量值,只需要将变量作为闭包的入参传入,提交时就会完成值拷贝:

func main() {
    for i := 0; i < 5; i++ {
        ii := i
        go func(ii int) {
            fmt.Println(ii) // 输出0-4的随机顺序
        }(ii)
        ii = 10
    }
    time.Sleep(100 * time.Millisecond)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:45:00