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 催更。

推荐阅读

相关推荐
zhuyasen2 小时前
在某些 Windows 版本,Go 1.25.x 编译出来的 exe 运行报错:此应用无法在你的电脑上运行
windows·go·编译器
用户89535603282205 小时前
深入浅出 Go slices 包:类型安全、内存安全与高性能实践
go
王中阳Go9 小时前
Python 的 PyPy 能追上 Go 的性能吗?
后端·python·go
gopyer1 天前
180课时吃透Go语言游戏后端开发11:Go语言中的并发编程
golang·go·游戏开发·并发编程
Java陈序员1 天前
简单好用!一款针对 IT 团队开发的文档管理系统!
mysql·docker·go
程序员爱钓鱼2 天前
Go语言实战案例——进阶与部署篇:性能优化与 pprof 性能分析实践
后端·google·go
程序员爱钓鱼2 天前
Go语言实战案例——进阶与部署篇:使用Go编写系统服务(如守护进程)
后端·google·go
n8n3 天前
Go语言GC调优全面指南
go
n8n3 天前
Go 协程在实际项目中的应用详解
go
苏琢玉3 天前
再也不用翻一堆日志!一键部署轻量级错误监控系统,帮你统一管理 PHP 报错
go·github·php