go中for range的坑以及解决方案
2024-01-10 14:36:11
一、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?了
文章来源:https://blog.csdn.net/fbbqt/article/details/135499133
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!