Go 1.22版本开始,for循环的每次迭代都会创建新的变量,解决了之前range的value只初始化一次的问题[2][6]. 在Go 1.22之前的版本中,for循环的变量只创建一次,并在每次迭代中被赋予对应的值,这容易导致一些错误[6].
示例
在Go 1.22之前的版本,使用for range可能会出现以下问题[3]:
func fr1() {
arr := []int{1, 2, 3}
for _, val := range arr {
go func() {
time.Sleep(time.Millisecond * 100)
fmt.Println(val)
}()
time.Sleep(time.Second)
}
}
// 输出结果:3 3 3
由于循环变量val只会被声明和初始化一次,在快速的循环迭代中,每个goroutine中引用的val实际上是同一个变量,等到goroutine真正开始执行的时候,for循环已经结束,val的值变成了最后一次循环的值[3].
解决方法
在Go 1.22之前,可以通过创建局部变量来解决这个问题[3]:
func fr1() {
values := []int{1, 2, 3, 4, 5}
for _, val := range values {
// 在这加入临时变量
val := val
go func() {
time.Sleep(time.Millisecond * 100)
fmt.Println(val)
}()
time.Sleep(time.Second)
}
}
// 输出结果:2 3 1 4 5 或 5 3 4 1 2 等无序结果
从Go 1.22开始,每次迭代都会创建新的变量,因此不再需要使用局部变量来解决这个问题[2][6].
package main
import (
"fmt"
"time"
)
func main() {
s := []string{"a", "b"}
for _, v := range s {
go func() {
fmt.Print(v)
}()
time.Sleep(time.Second * 1)
}
}
//输出结果:ab 或者 ba
Citations:
[1] https://www.cnblogs.com/zhangmingcheng/p/17389930.html
[2] https://www.sohu.com/a/821236021_100093134
[3] https://blog.youkuaiyun.com/fbbqt/article/details/135499133
[4] https://tonybai.com/2024/05/30/go-1-23-foresight/
[5] https://github.com/0voice/Introduction-to-Golang/blob/main/Golang%20%E6%96%B0%E6%89%8B%E5%8F%AF%E8%83%BD%E4%BC%9A%E8%B8%A9%E7%9A%84%2050%20%E4%B8%AA%E5%9D%91.md
[6] https://blog.youkuaiyun.com/luduoyuan/article/details/136264088
[7] https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-for-range/
[8] https://juejin.cn/post/7226657177103106104
[9] https://blog.youkuaiyun.com/qq_53267860/article/details/124866499
649

被折叠的 条评论
为什么被折叠?



