不知道各位看官对for循环了解多少,本文来和大家详细聊聊for相关的知识,介绍两个相关案例,希望能给大家带来帮助。
一起聊聊Go语言中的for循环
案例一:取地址符
我们在编写 for 语句时经常会出现运行和猜想的结果不一致。例如以下第一个案例的代码:
var all []*Itemfor _, item := range items { all = append(all, &item) }
在 for 循环时,每次存入变量 all 的都是相同的 item,也就是最后一个循环的 item 值。
这是 Go 面试里经常出现的题目,如果想解决这个问题,就需要把程序改写成如下:
var all []*Itemfor _, item := range items { item := item all = append(all, &item) }
要重新声明一个 item 变量把 for 循环的 item 变量给存储下来再追加进去。
案例二:闭包函数
接下来是第二个案例的代码:
var prints []func()for _, v := range []int{1, 2, 3} { prints = append(prints, func() { fmt.Println(v) }) }for _, print := range prints { print() }
这段程序的输出结果是什么?没有 & 取地址符,是输出 1,2,3 吗?不是的。
输出结果是 3,3,3。问题的重点之一,关注到闭包函数,实际上所有闭包都打印的是相同的 v。输出 3,是因为在 for 循环结束后,最后 v 的值被设置为了 3,仅此而已。
如果想要达到预期的效果,依然是使用万能的再赋值。改写后的代码如下:
for _, v := range []int{1, 2, 3} { v := v prints = append(prints, func() { fmt.Println(v) }) }
解决方案
在每个迭代变量 x 的每个循环体开头,加一个隐式的再赋值,也就是 x := x,就能够解决上述程序中所隐含的坑。
Go 1.30 或更高版本将会每次迭代变量,而早期 Go 版本的将每次循环变量,如此一来上述提到的 for 循环问题都会在一定范围内被解决。
以上就是本文的全部内容,翼速应用平台内有更多相关资讯,欢迎查阅!
我来说两句