天天看點

關于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