Pointers 从结构指针数组创建映射

Pointers 从结构指针数组创建映射,pointers,dictionary,struct,go,Pointers,Dictionary,Struct,Go,我有一个指向结构的指针数组。结构有一个名称字段。我想创建一个从名称到结构指针的映射 为什么注册表中的所有值都相同 package main import "fmt" type Thing struct { Name string Value int } type Registry map[string]*Thing func toRegistry(things *[]Thing) Registry { registry := make(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]

编辑 根据@tvblah的建议,
东西
已经是一个片段,所以没有必要指出它:

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)

每个映射值都是一个指向单个局部变量
的指针

一种修复方法是添加指向切片元素的指针:

func toRegistry(things []Thing) Registry {

  registry := make(Registry)

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

另一个选项是将指向
对象的指针存储在切片中:

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


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

每个映射值都是指向单个局部变量的指针
thing

一种修复方法是添加指向切片元素的指针:

func toRegistry(things []Thing) Registry {

  registry := make(Registry)

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

另一个选项是将指向
对象的指针存储在切片中:

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


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

您可以在每次迭代中将
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)

}

您可以在每次迭代中将
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)

}

@tvblah的解决方案会更有效吗?@mheiber这三种解决方案在逻辑上是不同的。这一个存储指向新分配的
对象的指针。我的第一个解决方案存储指向slice元素的指针。我的第二个解决方案存储切片中的指针。应用程序中的逻辑可能决定选择。这个解决方案在循环的每次迭代中分配一个
对象。我的解决方案没有。额外的分配对性能的影响微乎其微。@mheiber,由于分配了新变量,我的解决方案效率稍低。@tvblah的解决方案效率会更高吗?@mheiber这三种解决方案在逻辑上是不同的。这一个存储指向新分配的
对象的指针。我的第一个解决方案存储指向slice元素的指针。我的第二个解决方案存储切片中的指针。应用程序中的逻辑可能决定选择。这个解决方案在循环的每次迭代中分配一个
对象。我的解决方案没有。额外的分配对性能的影响可以忽略不计。@mheiber,由于分配了新变量,我的解决方案效率稍低。这是正确的答案。行为非常微妙,因此如果在原始示例
&thing
中不清楚,则返回循环中局部变量的地址。规范中说“它们的作用域是”for“语句的块;它们在每次迭代中都会重复使用。”因此,既然
thing
每次地址都是相同的变量,那么这就是正确的答案。行为非常微妙,因此如果在原始示例
&thing
中不清楚,则返回循环中局部变量的地址。规范中说“它们的作用域是”for“语句的块;它们在每次迭代中都会被重复使用。”因此,由于
thing
每次地址都是相同的变量。