引用自 http://studygolang.com/articles/9701
go只提供了一種循環方式,即for循環,在使用時可以像c那樣使用,也可以通過for range方式遍歷容器類型如數組、切片和映射。但是在使用for range時,如果使用不當,就會出現一些問題,導致程序運行行為不如預期。比如,下面的示例程序將遍歷一個切片,並將切片的值當成映射的鍵和值存入,切片類型是一個int型,映射的類型是鍵為int型,值為*int,即值是一個地址。
package main import "fmt" func main() { slice := []int{0, 1, 2, 3} myMap := make(map[int]*int) for index, value := range slice { myMap[index] = &value } fmt.Println("=====new map=====") prtMap(myMap) } func prtMap(myMap map[int]*int) { for key, value := range myMap { fmt.Printf("map[%v]=%v\n", key, *value) } }
運行程序輸出如下:
=====new map===== map[3]=3 map[0]=3 map[1]=3 map[2]=3
由輸出可以知道,不是我們預期的輸出,正確輸出應該如下:
=====new map===== map[0]=0 map[1]=1 map[2]=2 map[3]=3
但是由輸出可以知道,映射的值都相同且都是3。其實可以猜測映射的值都是同一個地址,遍歷到切片的最后一個元素3時,將3寫入了該地址,所以導致映射所有值都相同。其實真實原因也是如此,因為for range創建了每個元素的副本,而不是直接返回每個元素的引用,如果使用該值變量的地址作為指向每個元素的指針,就會導致錯誤,在迭代時,返回的變量是一個迭代過程中根據切片依次賦值的新變量,所以值的地址總是相同的,導致結果不如預期。
修正后程序如下:
package main import "fmt" func main() { slice := []int{0, 1, 2, 3} myMap := make(map[int]*int) for index, value := range slice { num := value myMap[index] = &num } fmt.Println("=====new map=====") prtMap(myMap) } func prtMap(myMap map[int]*int) { for key, value := range myMap { fmt.Printf("map[%v]=%v\n", key, *value) } }
運行程序輸出如下:
=====new map===== map[2]=2 map[3]=3 map[0]=0 map[1]=1