Reputation: 5201
I was trying to test the exact type of an object (either a costume struct or interface) in golang and was trying to figure out how to do it a way that does not real like a cheap hack. (Notice that built in types like strings, ints, floats, slices, etc are not what I am asking about).
Say that I have a Animal interface that implements a Speak method:
type Animal interface {
Speak() string
}
and a Dog struct that implements that interface:
type Dog struct {
}
func (d Dog) Speak() string {
return "Woof!"
}
say I have some variable x, how do I check what struct type it has and act accordingly?
For example I wanted something like:
func isDog(thing Animal{}) bool {
if reflect.TypeOf(thing) == packageName.Dog{
return true
}else{
return false
}
}
The only solution that I thought of doing was not really what I wanted to do but I guess it works. First create an empty struct of the type I want to check and then use the reflect package to check for equality. Something like:
func isDog(thing Interface{}) bool {
d := Dog{}
if reflect.TypeOf(thing) == reflect.TypeOf(d){
return true
}else{
return false
}
}
The reason I didn't really like that is, say I have a larger code that I need a switch statement eventually. Then, I have to write so much extra code that I feel is unnecessary, like, I need to create the number of many empty struct types as I have cases. It seems unnecessary and really ugly. Is that the only way to do it? I also wanted it to be flexible enough to me it check for pointers too. Something like:
func isDog(thing Interface{}) bool {
d := Dog{}
if reflect.TypeOf(thing) == packageName.Dog{
return true
}else if reflect.TypeOf(thing) == *packageName.Dog{
return true
}else{
return false
}
}
Upvotes: 1
Views: 580
Reputation: 21
The idiomatic way is to use a type switch rather than type assertions directly.
func isDog(animal Animal) bool {
switch animal.(type) {
case Dog:
case *Dog:
default:
return false
}
return true
}
Upvotes: 2
Reputation: 43899
To determine the dynamic type of an interface variable, you can use the two-return form of a type assertion. For example, your isDog
function could be implemented as:
func isDog(thing Animal) bool {
_, isdog := thing.(packageName.Dog)
_, isdogptr := thig.(*packageName.Dog)
return isdog || isdogptr
}
Upvotes: 3