Go:比较接口类型的映射

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

Go: Comparison in maps of interface types

问题

假设我有很多不同的结构类型,它们都满足一个接口Food

type Food interface {
    Name() string
    Tastiness() int
}

type fruit struct {
    species  string
    numSeeds int
}

type vegetable struct {
    commonName string
    weight  int
}

func (f *fruit) Name() string       { return f.species }
func (f *fruit) Tastiness() int     { return 100 - f.numSeeds }
func (v *vegetable) Name() string   { return v.commonName }
func (v *vegetable) Tastiness() int { return 1 }

满足Food接口的结构体使用的是具有指针接收器的函数,因为我经常传递它们,如果没有指针,这将变得很麻烦。

通常,我想要比较food1food2,所以我构建了类似于foodmap := map[Food]bool的映射。我真正想要检查的是底层结构体是否相同。但是,由于始终是指针满足接口,如果我创建了两个相同类型的fruitvegetable,我无法使用映射或列表进行相等性或存在性测试。

比较Food的最佳方法是使用map[Food]bool,而是使用类似于map[FoodKey]的东西,其中任何满足Food的结构体都提供一个FoodKey() comparisonStruct方法,该方法返回一个专门用于比较的结构体。

英文:

Let's say I have a lot of different struct types which all satisfy an interface, Food.

type Food interface {
	Name() string
	Tastiness() int
}

type fruit struct {
	species  string
	numSeeds int
}

type vegetable struct {
	commonName string
	weight  int
}

func (f *fruit) Name() string       { return f.species }
func (f *fruit) Tastiness() int     { return 100 - f.numSeeds }
func (v *vegetable) Name() string   { return v.commonName }
func (v *vegetable) Tastiness() int { return 1 }

The structs that satisfy the Food interface do so with functions that are pointer receivers because I pass them around often, which is unwieldy without pointers.

Often, I want to make comparisons between food1 and food2, and so I construct maps that look like foodmap := map[Food]bool. What I really want to check is if the underlying structs are the same thing. But, because it's always pointers that are satisfying the interface, I can't do equality or presence tests using maps or lists if I create two of the same kind of fruit or vegetable, for example.

Is the best way to compare Foods to not use map[Food]bool and instead use something like map[FoodKey], where any struct that satsifies Food provides a FoodKey() comparisonStruct method that returns a struct meant strictly for comparison?

答案1

得分: 1

最好的比较食物的方法是不使用map[Food]bool,而是使用类似map[FoodKey]的结构,其中任何满足Food接口的结构都提供一个FoodKey() comparisonStruct方法,该方法返回一个严格用于比较的结构体。

我怀疑这是一个更好的方法,考虑到以下几点:

英文:

> Is the best way to compare Foods to not use map[Food]bool and instead use something like map[FoodKey], where any struct that satsifies Food provides a FoodKey() comparisonStruct method that returns a struct meant strictly for comparison?

I suspect it is a better approach, considering:

答案2

得分: 1

我相信在这里最有效的方法是在你的接口中添加一个额外的函数,比如Is(f Food) bool,它很容易实现,没有使用反射或比较接口或使用映射的开销。

示例:

type Food interface {
    Name() string
    Tastiness() int
    Is(f Food) bool
}
//....
func (*fruit) Is(f Food) bool   { _, ok := f.(*fruit); return ok }
//....
func (*vegetable) Is(f Food) bool   { _, ok := f.(*vegetable); return ok }

playground

英文:

I believe the most efficient path here is to add an extra function to your interface like Is(f Food) bool, it's easy to implement, no overhead of using reflection or comparing interfaces or using a map somewhere.

Example:

type Food interface {
	Name() string
	Tastiness() int
	Is(f Food) bool
}
//....
func (*fruit) Is(f Food) bool   { _, ok := f.(*fruit); return ok }
//....
func (*vegetable) Is(f Food) bool   { _, ok := f.(*vegetable); return ok }

<kbd>playground</kbd>

答案3

得分: 0

你有两种方法来确定或比较接口的底层结构。

1- 使用 reflect 包,具体来说是 reflect.TypeOf 函数,它将返回接口的动态类型,例如:

x := Food(fruit{"banana", 0})
y := Food(vegetable{"potato", 45})
return reflect.TypeOf(x) == reflect.TypeOf(y)

这段代码将返回 false。

2- 使用类型断言或 类型切换,例如:

value, ok := yourInterface.(possibleType)
英文:

You have two options to determine or compare the underlying structs of interfaces.

1- Use the reflect package, specifically the reflect.TypeOf function, which will return the dynamic type of the interface, such as:

x := Food(fruit{&quot;banana&quot;, 0})
y := Food(vegetable{&quot;potato, 45})
return reflect.TypeOf(x) == reflect.TypeOf(y)

This piece of code will return false.

2- Use type assertions or a type switch, such as:

value, ok := yourInterface.(possibleType)

huangapple
  • 本文由 发表于 2014年8月7日 18:47:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/25180509.html
匿名

发表评论

匿名网友

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

确定