2016-04-28 55 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] 
} 
相关问题