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

问题描述 投票:0回答:3

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

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()
}

结果:

src map[1:1 2:2 3:3]
3 3 3

去游乐场: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)
}

这看起来很尴尬。

for-loop go reference
3个回答
8
投票

如果您有一个

map[T]X
并且您想获得一个
[]*T
,那么您就走在正确的轨道上,复制循环变量并获取它的地址。

有一个比你的方法稍微精简的方法:

for k := range src {
    key := k
    dst = append(dst, &key)
}

您添加到 dst 的不是映射中键或值的地址,而是键的“副本”的地址。这种区别对你来说可能很重要,也可能不重要。 使用循环变量的地址不起作用的原因是循环变量是在每次迭代时更新的单个位置。每次将整数和结构等值类型分配给新变量时,都会复制它。


1
投票

for i, _ := range src { dst = append(dst, &src[i]) }



0
投票

type User struct { id int ... } func (u *User) ID() int { return u.id } users := []User{ ... } indexByID := make(map[int]&User, len(users)) for i := range users { p := &users[i] indexByID[p.ID()] = &p }

© www.soinside.com 2019 - 2024. All rights reserved.