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

Go循环指针行为差异原因及Go 1.22版本变更疑问

Go 1.19循环指针问题解答

问题1:两个for range循环结果差异的原因

第一个循环输出3 3 3的本质

在Go 1.19及更早版本中,for range迭代切片时,循环变量是复用的同一个内存地址。整个循环过程里,key始终是同一个变量,每次迭代只是把切片当前元素的值覆盖到这个变量上。

你在res[i] = task{key: &key}中保存的是这个复用变量的地址,当循环结束时,key的值已经被最后一个元素"3"覆盖,因此所有task的key指针都指向这个最终值,输出自然全是3。

对应代码片段:

keys := []string{"1", "2", "3"}
res := make([]task, len(keys))

for i, key := range keys {
    res[i] = task{key: &key} // 所有task的key指向同一个复用变量的地址
}

第二个循环能正确输出的原因

第二个循环里,managers中的每个task.key指向的是外部独立定义的key1、key2的地址,这两个变量不属于循环变量,不会被复用覆盖。

当你迭代managers时,虽然循环变量manager也是复用的,但你复制的是manager的值(其中包含指向key1/key2的指针)到result中。这些指针指向的是固定的、不会被修改的外部变量地址,所以最终能正确输出111和222。

不管是用append还是直接赋值result[i] = manager,结果都正确,因为复制的指针指向的是独立变量,不受循环复用影响。

问题2:Go 1.22的行为修改

你的理解完全正确,Go 1.22对for range循环变量的行为做了根本性修改:每次迭代都会创建新的循环变量,不再复用同一个内存地址。

这意味着原来第一个循环的代码在Go 1.22中会直接输出1 2 3,不需要额外创建临时变量来规避问题。

Go 1.19下的修复方案

如果要在Go 1.19中让第一个循环输出正确结果,只需要在循环内部创建临时变量保存当前迭代值,再取临时变量的地址:

for i, key := range keys {
    tempKey := key // 每次循环生成新的临时变量,地址唯一
    res[i] = task{key: &tempKey}
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:34:52