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

After I copy all items from a slice (src) into a new slice (dst) all items in dst point to the last item of 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
", i, *s)
    }
}

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

Why aren't "a" and "b" copied into the dst slice?

The solution is simple, but counter intuitive in terms of what you would expect of the range statement.

The variable val is instantiated only once and holds the value of src[i] in every iteration. It does not has the actual pointer to src[i]. Instead the value of src[i] is copied to the memory that is assigned to val. By taking the pointer of val you get exactly that, and not the pointer to 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
", i, *s, s)
    }

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

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

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

While in hindsight this is obvious - for _, val -> := <- range src - it can can bite you in the ass if you are unaware of it, so therefore this warning.

PS. this also applies to src as a map.

Adding to @RickyA's answer.

To achieve what you were trying to do you need to do:

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