如何为Go地图指定指针

jor*_*175 2 dictionary pointers go

我在分配指向地图的指针时遇到问题.也许这是Go中的一个错误?或许我只是做错了什么.代码也在操场上,https://play.golang.org/p/p0NosPtkptz

这是一些说明问题的超简化代码.我正在创建一个名为collections的对象,其中包含两个集合对象.然后我循环遍历这些集合并将它们分配给地图,其中地图中的键是集合ID.

package main

import (
    "fmt"
)

type collection struct {
    ID string
    Name string
}

type collections struct {
    Collections []collection
}

type cache struct {
    Index int
    Collections map[string]*collection
}

func main() {
    var c cache
    c.Collections = make(map[string]*collection)

    // Create 2 Collections
    var col1, col2 collection
    col1.ID = "aa"
    col1.Name = "Text A"
    col2.ID = "bb"
    col2.Name = "Test B"

    // Add to Collections
    var cols collections
    cols.Collections = append(cols.Collections, col1)
    cols.Collections = append(cols.Collections, col2)
    fmt.Println("DEBUG Collections Type", cols)

    i := 0
    for k, v := range cols.Collections {
        c.Index = i
        c.Collections[v.ID] = &v
        fmt.Println("DEBUG k", k)
        fmt.Println("DEBUG v", v)
        i++
    }
    fmt.Println("Collection 1", c.Collections["aa"].ID)
    fmt.Println("Collection 2", c.Collections["bb"].ID)
    fmt.Println(c)
}
Run Code Online (Sandbox Code Playgroud)

此游乐场代码的输出如下所示:

DEBUG Collections Type {[{aa Text A} {bb Test B}]}
DEBUG k 0
DEBUG v {aa Text A}
DEBUG k 1
DEBUG v {bb Test B}
Collection 1 bb
Collection 2 bb
{1 map[aa:0x1040a0f0 bb:0x1040a0f0]}
Run Code Online (Sandbox Code Playgroud)

所以看起来地图是出于某种原因为每个条目获取相同的指针.所有的"DEBUG"行打印出我所期望的.但是,三条印刷线在最后,没有.集合1应该是"aa"而不是"bb".

aer*_*ite 6

当你把&vc.Collections[v.ID],你实际上是分配循环变量的地址相同v.

此地址最终保存列表的最后一个值.这就是为什么你要获得bb Test B所有关键.

打印这些值,您将看到相同的地址.

fmt.Printf("%p\n", c.Collections["aa"])
fmt.Printf("%p\n", c.Collections["bb"])
Run Code Online (Sandbox Code Playgroud)

通过将其复制到循环范围中的新变量,问题就解决了.循环中的每个步骤都会将一个新的唯一地址放入缓存中.

for k, v := range cols.Collections {
    coll := v
    c.Collections[v.ID] = &coll
    fmt.Println("DEBUG k", k)
    fmt.Println("DEBUG v", v)
    i++
}
Run Code Online (Sandbox Code Playgroud)