写在前面
迭代变量的使用,在立即执行的函数中,一般是不会显现问题的,但是在延迟执行的函数中,就会出现致命的问题。
立即执行的情况
当然,这种例子有很多,这里举一个非常简单的例子分析一下。场景需求:将silce内的数字迭代输出即可。
package main
import "fmt"
func main() {
var numsSilces []int
for i:=0; i<10; i++ {
numsSilces = append(numsSilces, i)
}
for _, num := range numsSilces {
fmt.Println(num)
}
}
这样的程序运行无任何问题,输出0-9
延迟执行的情况
一般说到延迟运行,在Go语言中,使用较多的是defer这个关键字,这里主要是以较为特殊的例子进行说明。代码见下:
package main
/**
主要涉及到go语言中的迭代变量的捕获
*/
import "fmt"
func main() {
var handles []func()
var numsSilces []int
for i:=0; i<10; i++ {
numsSilces = append(numsSilces, i)
}
for _, num := range numsSilces {
handles = append(handles, func() {
fmt.Println(num)
})
}
for _, handle := range handles {
handle()
}
}
输出结果均为9。其实看到输出结果,也基本可以推断出程序运行的过程了,这里的迭代变量num,其并非指向的是一个固定的值,其指向的是一个可访问的存储位置,每一次迭代的过程,都是将迭代的获得值写入到了这个固定的存储位置中。存储位置不变,但存储的值会伴随着迭代的次数进行更新,所以最终num的值全部指向的是9。
问题解决
出现这种问题时,一般是采用引入一个内部变量,并利用迭代变量进行初始化的方式,对每一次迭代的值进行保存。如下:
package main
/**
主要涉及到go语言中的迭代变量的捕获
*/
import "fmt"
func main() {
var handles []func()
var numsSilces []int
for i:=0; i<10; i++ {
numsSilces = append(numsSilces, i)
}
for _, num := range numsSilces {
num := num //引入内部变量对值进行保存,并采用迭代变量的值进行初始化
handles = append(handles, func() {
fmt.Println(num)
})
}
for _, handle := range handles {
handle()
}
}
感觉这种坑是自己以后可能会遇到的,所以还是提前记录一下。