2016-04-28 32 views
2

將所有項目從片段(src)複製到新片段(dst)後,dst中的所有項目都指向src的最後一項。golang範圍複製後,所有項目指向src片段的最後一項

package main 

import (
    "fmt" 
) 

func main() { 
    src := []string{"a", "b", "c"} 
    dst := []*string{} 
    for _, val := range src { 
     dst = append(dst, &val) 
    } 

    for i, s := range dst { 
     fmt.Printf("%v - %v\n", i, *s) 
    } 
} 

>>> 0 - c 
>>> 1 - c 
>>> 2 - c 

爲什麼「a」和「b」沒有複製到dst slice中?

+0

我不會將其標記爲重複的,因爲你已經得到了一些很好的答案,但見:https://golang.org/ DOC/FAQ#closures_and_goroutines – JimB

回答

6

該解決方案很簡單,但是根據您對range聲明的期望而言並不直觀。

變量val僅實例化一次,並且在每次迭代中保持的值src[i]。它沒有指向src[i]的實際指針。而是將src[i]的值複製到分配給val的內存中。通過採用val的指針,您可以得到完全的結果,而不是指向src[i]的指針。

package main 

import (
    "fmt" 
) 

func main() { 
    src := []string{"a", "b", "c"} 
    dst := []*string{} 
    for _, val := range src { 
     dst = append(dst, &val) 
    } 

    for i, s := range dst { 
     fmt.Printf("%v - %v - %p\n", i, *s, s) 
    } 

    //modify only contents of first index 
    *dst[0] = "hi val" 

    for i, s := range dst { 
     fmt.Printf("%v - %v - %p\n", i, *s, s) 
    } 
} 

>>>> 
0 - c - 0x1040a120 
1 - c - 0x1040a120 
2 - c - 0x1040a120 
0 - hi val - 0x1040a120 
1 - hi val - 0x1040a120 
2 - hi val - 0x1040a120 

雖然在事後,這是顯而易見的 - for _, val - >:= < - range src - 它可以可以咬你的屁股,如果你不知道它,所以因此此警告。

PS。這也適用於src作爲地圖。

4

添加到@ RickyA的回答。

要實現你試圖做你需要做的:

for i := range src { 
    dst[i] = &src[i] 
} 
相關問題