Go1.22填上for range大坑

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值