天天看点

关于Go语言中的迭代变量的分析

写在前面

迭代变量的使用,在立即执行的函数中,一般是不会显现问题的,但是在延迟执行的函数中,就会出现致命的问题。

立即执行的情况

当然,这种例子有很多,这里举一个非常简单的例子分析一下。场景需求:将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()
	}
}
           

感觉这种坑是自己以后可能会遇到的,所以还是提前记录一下。

go