Go1.22 新特性:for 循环不再共享循环变量,且支持整数范围

大家好,我是煎鱼。

又过了好几个月,到了 Go 新版本的日子了。Go 1.22 预计将于 2024 年 2 月发布。我将会给大家带来一系列的新版本特性讲解和分享。

今天这篇文章主要是针对 for 循环的特性变更。

不再共享循环变量

在老版本的 Go 中,for 循环迭代器的变量是一个单一变量,在每个循环迭代中仅是取值不同。这样做在性能上非常高效,但如果使用不当,会导致意想不到的行为,可能会造成共享循环变量的问题。

最经典的场景就是在 goroutine 循环时的问题。如下代码:

go 复制代码
func main() {
	values := []int{1, 2, 3, 4, 5}
	for _, val := range values {
		go func() {
			fmt.Printf("%d ", val)
		}()
	}
	time.Sleep(time.Second * 3)
}

输出结果:

5 5 5 5 5

如果是 Go1.22 以前的版本,在不做任何变更的情况下。我们需要把代码改成如下:

go 复制代码
func main() {
	values := []int{1, 2, 3, 4, 5}
	for _, val := range values {
		go func(val int) {
			fmt.Printf("%d ", val)
		}(val)
	}
	time.Sleep(time.Second * 3)
}

其他场景下,,也会需要写 v := v 的代码来再次赋值。经典的很。

但在 Go1.22 起,不再需要这么干了。之前文章《Go 团队将修改 for 循环变量的语义,Go1.21 新版本即可体验!》提到的 GOEXPERIMENT=loopvar 特性已经默认加到该版本。语法将默认改变。

也就是在 Go 1.22 中,for 循环的每次迭代都会创建新变量,每次循环自己迭代自己的变量,以避免意外共享错误。上面一模一样的代码,输出结果不再是固定的 5。

而是非固定、非稳定有序的值,例如:2 4 3 5 1 等随机结果。

如下输出:

arduino 复制代码
// 运行第一次
2 3 1 4 5
// 运行第二次
2 3 1 5 4
// 运行第三次
5 1 2 3 4
...

很多面试官喜欢拿这个来做面试题。敲黑板了,请大家改一下面试题和答案了。

支持循环整数类型

在 for 循环中,对整数类型的范围进行循环迭代。代码如下:

go 复制代码
func main() {
	for i := range 7 {
		fmt.Println("煎鱼", i)
	}
	fmt.Println("煎鱼进脑子了!")
}

在老版本的 Go 中,会直接报如下错误:

go 复制代码
$ go run demo.go
# command-line-arguments
./demo.go:8:17: cannot range over 7 (untyped int constant)

但在 Go1.22 起,支持了该功能特性。

输出结果:

煎鱼 0
煎鱼 1
煎鱼 2
煎鱼 3
煎鱼 4
煎鱼 5
煎鱼 6
煎鱼进脑子了!

算是补全一个 for 循环的小缺漏。

总结

在 Go1.22 起,对 for 循环的共享变量进行了一次整治,新版本将会采用新的语法进行。

如果对你的老代码升级有影响,可以主动配置 GOEXPERIMENT=loopvar 来保持逻辑一致。

本次的整型类型范围的 for 循环支持,也算是填补和拓展了程序里的用法。

最后的最后,Go 面试题中有用到上述特性的同学,请注意修改问题和答案。免得没跟上新版本的迭代。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
煎鱼eddycjy3 小时前
新提案:由迭代器启发的 Go 错误函数处理
go
煎鱼eddycjy3 小时前
Go 语言十五周年!权力交接、回顾与展望
go
不爱说话郭德纲20 小时前
聚焦 Go 语言框架,探索创新实践过程
go·编程语言
0x派大星2 天前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin
IT书架2 天前
golang高频面试真题
面试·go
郝同学的测开笔记2 天前
云原生探索系列(十四):Go 语言panic、defer以及recover函数
后端·云原生·go
秋落风声3 天前
【滑动窗口入门篇】
java·算法·leetcode·go·哈希表
0x派大星5 天前
【Golang】——Gin 框架中的模板渲染详解
开发语言·后端·golang·go·gin
0x派大星5 天前
【Golang】——Gin 框架中的表单处理与数据绑定
开发语言·后端·golang·go·gin
三里清风_6 天前
如何使用Casbin设计后台权限管理系统
golang·go·casbin