在Go中复制循环变量的地址

Ral*_*lph 1 for-loop reference go

在下面的代码示例中,结果不是我期望的:

package main

import "fmt"

func main() {
    src := map[int]int{1: 1, 2: 2, 3: 3}
    fmt.Println("src ", src)

    dst := make([]*int, 0, len(src))
    for k, _ := range src {
        dst = append(dst, &k)
    }
    for _, a := range dst {
        fmt.Print(*a, " ")
    }
    fmt.Println()
}
Run Code Online (Sandbox Code Playgroud)

结果:

src map[1:1 2:2 3:3]
3 3 3
Run Code Online (Sandbox Code Playgroud)

前往游乐场:https : //play.golang.org/p/BSDsd3nojz

但我知道发生了什么事。的不变地址k被添加到dst,因此当我循环遍历时dst,每个位置都有相同的值:3

k在循环中,永不改变的地址,因此第二个循环继续引用该位置,其中包含其最后一个值3

如何获取k要复制的当前值的地址?我需要这样的东西吗:

for k, _ := range src {
    key = new(int)
    *key = k
    dst = append(dst, key)
}
Run Code Online (Sandbox Code Playgroud)

好像很尴尬

cap*_*aig 5

如果您有一个,map[T]X并且想要获得一个[]*T,那么您将在正确的轨道上复制循环变量并为其获取地址。

有一种比您的方法更苗条的方法:

for k := range src {
    key := k
    dst = append(dst, &key)
}
Run Code Online (Sandbox Code Playgroud)

您要添加到dst的不是键的地址或映射中的值,而是键的副本的地址。这种区分可能对您无关紧要。

使用循环变量的地址不起作用的原因是,循环变量是单个位置,每次迭代都会更新。每次将值分配给新变量时,都会复制诸如int和structs的值类型。