从struct指针数组创建映射

时间:2015-04-20 02:26:14

标签: pointers dictionary struct go

我有一个指向结构的指针数组。结构具有name字段。我想创建一个从名称到指向结构的指针的地图。

为什么registry地图中的所有值都相同?

package main

import "fmt"

type Thing struct {
    Name  string
    Value int
}

type Registry map[string]*Thing

func toRegistry(things *[]Thing) Registry {

    registry := make(Registry)

    for _, thing := range *things {
        registry[thing.Name] = &thing
    }
    return registry
}

func main() {

    things := []Thing{{"thingA", 1}, {"thingB", 2}}
    registry := toRegistry(&things)
    fmt.Println(registry)

}

示例输出:map[thingB:0x10436180 thingA:0x10436180]

GO

修改

Per @ tvblah的建议,things已经是一片,所以没有必要指出它:

package main

import "fmt"

type Thing struct {
    Name  string
    Value int
}

type Registry map[string]*Thing

func toRegistry(things []Thing) Registry {

    registry := make(Registry)

    for _, thing := range things {
        registry[thing.Name] = &thing
    }
    return registry
}

func main() {

    things := []Thing{{"thingA", 1}, {"thingB", 2}}
    registry := toRegistry(things)
    fmt.Println(registry)

GO

2 个答案:

答案 0 :(得分:3)

每个地图值都是指向单个局部变量thing的指针。

一个解决方法是添加一个指向切片元素的指针:

func toRegistry(things []Thing) Registry {

  registry := make(Registry)

  for i := range things {
    registry[things[i].Name] = &things[i]
  }
  return registry
}

playground

另一种选择是在切片中存储指向Thing的指针:

func toRegistry(things []*Thing) Registry {
  registry := make(Registry)
  for _, thing := range things {
    registry[thing.Name] = thing
  }
  return registry
}

func main() {
  things := []*Thing{&Thing{"thingA", 1}, &Thing{"thingB", 2}}
  registry := toRegistry(things)
  fmt.Println(registry)
}

playground

我将函数参数从指向切片的指针更改为切片。此更改对此问题提出的问题没有影响,但通常是Go代码的编写方式。 Go中很少使用切片指针。

答案 1 :(得分:2)

您可以在每次迭代时将thing重新分配给另一个局部变量,并将新变量存储在注册表中。

package main

import "fmt"

type Thing struct {
    Name  string
    Value int
}

type Registry map[string]*Thing

func toRegistry(things *[]Thing) Registry {

    registry := make(Registry)

    for _, thing := range *things {
        t := thing
        registry[thing.Name] = &t
    }
    return registry
}

func main() {

    things := []Thing{{"thingA", 1}, {"thingB", 2}}
    registry := toRegistry(&things)
    fmt.Println(registry)

}

Playground