从结构指针数组创建地图

huangapple go评论78阅读模式
英文:

Creating a map from an array of struct pointers

问题

我有一个指向结构体的指针数组。这些结构体有一个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

根据@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](https://play.golang.org/p/tbZt6WWyEd)
英文:

I have an array of pointers to structs. The structs have a name field. I want to create a map from names to pointers to structs.

Why are all of the values in the registry map identical?

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)

}

Sample output: map[thingB:0x10436180 thingA:0x10436180]

GO

EDIT

Per @tvblah's suggestion, things was already a slice, so there's no need to point to it:

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

答案1

得分: 3

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

一种修复方法是在切片元素中添加一个指针:

func toRegistry(things []Thing) Registry {
  registry := make(Registry)
  for i := range things {
    registry[things[i].Name] = &things[i]
  }
  return registry
}

另一种选择是在切片中存储指向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)
}

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

英文:

Each map value is a pointer to the single local variable thing.

One fix is to add an pointer to the slice element:

func toRegistry(things []Thing) Registry {

  registry := make(Registry)

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

playground

Another option is to store pointers to Thing in the slice:

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

I changed the function argument from a pointer to a slice to a slice. This change has no impact on the issue raised on the question, but it's generally how Go code is written. Pointers to slices are rarely used in Go.

答案2

得分: 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

英文:

You may reassign thing to another local variable on each iteration and store new variable in 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 {
		t := thing
		registry[thing.Name] = &t
	}
	return registry
}

func main() {

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

}

Playground

huangapple
  • 本文由 发表于 2015年4月20日 10:26:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/29738391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定