在golang范围复制后,所有项目都指向src切片的最后一个项目

在golang范围复制后,所有项目都指向src切片的最后一个项目,go,range,Go,Range,在我将一个切片(src)中的所有项复制到一个新切片(dst)中之后,dst中的所有项都指向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 :=

在我将一个切片(src)中的所有项复制到一个新切片(dst)中之后,dst中的所有项都指向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切片中?

解决方案很简单,但与您对
范围的期望相反

变量
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

事后看来,这一点很明显-
对于uval来说,val:=增加了@RickyA的答案

要实现您想要做的事情,您需要:

for i := range src {
    dst[i] = &src[i]
}

我不会将其标记为重复,因为您已经得到了一些很好的答案,但请参见: