Reputation: 31033
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 Food
s 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?
Upvotes: 1
Views: 1547
Reputation: 99431
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 }
Upvotes: 1
Reputation: 1820
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{"banana", 0})
y := Food(vegetable{"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)
Upvotes: 0
Reputation: 1330092
Is the best way to compare Foods to not use
map[Food]bool
and instead use something likemap[FoodKey]
, where any struct that satsifies Food provides aFoodKey() comparisonStruct
method that returns a struct meant strictly for comparison?
I suspect it is a better approach, considering:
Equaler
(as in this thread) isn't easyUpvotes: 1