接口作为映射键

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

Interfaces as map keys

问题

在以下代码中:

package main

import (
  "fmt"
)

type Object interface {
  String() string
}

type Person struct {
  Name string
}

func (p *Person) String() string {
  return fmt.Sprintf("person: %s", p.Name)
}

func main() {
  dict := map[Object]int{
    &Person{Name: "xyz"}: 4,
    &Person{Name: "gle"}: 2,
    &Person{Name: "kp3"}: 7,
  }

  fmt.Println(dict[&Person{Name: "xyz"}])
}

它只打印出 0,因为 map 的键是接口类型 Object。我知道为什么会发生这种情况,但是否有任何方法可以解决这个问题?我希望能够拥有一个键为接口类型的 map,但仍然可以访问字段。

到目前为止,我想到的唯一方法是遍历每个键并检查键是否等于我要搜索的内容,但这可能会非常慢。

英文:

In the following code:

package main

import (
  "fmt"
)

type Object interface {
  String() string
}

type Person struct {
  Name string
}

func (p *Person) String() string {
  return fmt.Sprintf("person: %s", p.Name)
}

func main() {
  dict := map[Object]int{
    &Person{Name: "xyz"}: 4,
    &Person{Name: "gle"}: 2,
    &Person{Name: "kp3"}: 7,
  }

  fmt.Println(dict[&Person{Name: "xyz"}])
}

It just prints 0, because the map's keys are Objects, which are interfaces. I know why this happens, but is there any way to get around it? I want to be able to have a map whose keys are interface types, but which I can still access fields of.

The only way I've thought of so far would be to iterate through each key and check if the key is equal to the thing I'm searching for, but it would likely be significantly slower.

答案1

得分: 4

如果您将方法定义在结构体上而不是指针上,它确实可以工作:https://play.golang.org/p/zU4sbFe2RB。

如果您无法在实际代码中这样做,恐怕您无法实现您想要的效果。即使这两个指针指向相似的数据,它们也将是不同的值。

您可以在Object接口中添加一个Equals(Object) bool方法,并自己实现一个映射。或者,您可以定义一个Hash() string方法,并使用map[string]whatever

英文:

It does work if you define your method on a struct rather than a pointer: https://play.golang.org/p/zU4sbFe2RB.

If you can't do that in real code, I'm afraid you can't accomplish what you want. These two pointers will be different values, even if they point to similar data.

You can add an Equals(Object) bool method to the Object interface and roll out your own implementation of a map. Alternatively, you can define Hash() string method and use a map[string]whatever.

答案2

得分: 3

这似乎是对映射的误用;如果你将映射的键设置为对象的String()值(对象唯一的共同属性),你可以尝试以下代码:

package main

import (
	"fmt"
)

type Object interface {
	String() string
}

type Person struct {
	Name string
}

func (p *Person) String() string {
	return fmt.Sprintf("person: %s", p.Name)
}

func main() {
	xyz := &Person{Name: "xyz"}
	gle := &Person{Name: "gle"}
	kp3 := &Person{Name: "kp3"}
	dict := map[string]int{
		xyz.String(): 4,
		gle.String(): 2,
		kp3.String(): 7,
	}

	fmt.Println(dict[xyz.String()])
}
英文:

This seems like it may be a misuse of maps; if you're keying the map off of the String() value of the objects (the only thing the objects have in common), you might try:

package main

import (
	"fmt"
)

type Object interface {
	String() string
}

type Person struct {
	Name string
}

func (p *Person) String() string {
	return fmt.Sprintf("person: %s", p.Name)
}

func main() {
	xyz := &Person{Name: "xyz"}
	gle := &Person{Name: "gle"}
	kp3 := &Person{Name: "kp3"}
	dict := map[string]int{
		xyz.String(): 4,
		gle.String(): 2,
		kp3.String(): 7,
	}

	fmt.Println(dict[xyz.String()])
}

huangapple
  • 本文由 发表于 2017年8月25日 04:40:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/45870518.html
匿名

发表评论

匿名网友

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

确定