go中for range的坑以及解决方案
作者:fbbqt
相信小伙伴都遇到过以下的循环变量的问题,本文主要介绍了go中for range的坑以及解决方案,具有一定的参考价值,感兴趣的可以了解一下
一、for range的坑
相信小伙伴都遇到过以下的循环变量的问题,那是因为循环的val变量是重复使用的,即仅有一份。也就是说,每次循环后赋给val的值就会把前面循环赋给val的值替换掉,所以打印出来的值都是最后一次循环赋给val的值。
1、例子
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 func fr2() { arr := [2]int{1, 2} arrnew := []*int{} for _, val := range arr { arrnew = append(arrnew, &v) } fmt.Println(*arrnew[0], *arrnew[1]) //输出结果: 2 2 }
2、解决方案
使用局部变量/临时变量,即可解决
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 等无序结果 //===========================或者============================= func fr1() { values := []int{1, 2, 3, 4, 5} for _, val := range values { //传入变量 go func(val int) { time.Sleep(time.Millisecond * 100) fmt.Println(val) }(val) } time.Sleep(time.Second) } //输出结果:2 3 1 4 5 或 5 3 4 1 2 等无序结果
二、官方解决方案
1、在Go1.21版本中,提前体验
可以设置 GOEXPERIMENT=loopvar,就会解决以上问题,运行代码时就不会出现以上的坑。
Windows中设置举例
go env -w GOEXPERIMENT=loopvar 或 $env:GOEXPERIMENT="loopvar"
> go env set GO111MODULE=on set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\Administrator\AppData\Local\go-build set GOENV=C:\Users\Administrator\AppData\Roaming\go\env set GOEXE=.exe set GOEXPERIMENT=loopvar set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOINSECURE= set GOMODCACHE=C:\Users\Administrator\go\pkg\mod
2、预计在 Go1.22 起,在go.mod中支持
新的 for 循环语义,将会在 go.mod 文件中的 go 行(版本声明大于等于 Go1.22 下)默认应用。也就不用设置 GOEXPERIMENT=loopvar 了
到此这篇关于go中for range的坑以及解决方案的文章就介绍到这了,更多相关go for range坑内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!