Go 1.22 可能将改变 for 循环变量的语义
几乎世界上每个 Golang 程序员都踩过一遍 for 循环变量的坑,而这个坑的解决方案已经作为实验特性加入到了 Go 1.21 中,并且有望在 Go 1.22 中完全开放。
举个例子,有这么段代码:
var ids []*int
for i := 0; i < 10; i++ {
ids = append(ids, &i)
}
for _, item := range ids {
println(*item)
}
可以试着在 playgound 里面运行下:go.dev/play/p/O8MVGtueGAf
答案是:打印出来的全是 10。
这个结果实在离谱。原因是因为在目前 Go 的设计中,for 中循环变量的定义是 per loop 而非 per iteration。也就是整个 for 循环期间,变量 i
只会有一个。以上代码等价于:
var ids []*int
var i int
for i = 0; i < 10; i++ {
ids = append(ids, &i)
}
同样的问题在闭包使用循环变量时也存在,代码如下: