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

推荐阅读

相关推荐
lekami_兰2 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘6 小时前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤6 小时前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt1119 小时前
AI DDD重构实践
go
Grassto2 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto4 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室5 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题5 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉7 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想
asaotomo7 天前
一款 AI 驱动的新一代安全运维代理 —— DeepSentry(深哨)
运维·人工智能·安全·ai·go