Is there a way I can determine which interfaces a concrete type implements from an arbitrary list of interfaces? I'm aware of a type switch, but I'd like to know all satisfied interfaces.
For example, given:
type Mover interface { Move() }
type Talker interface { Talk() }
type Flyer interface { Fly() }
type Person struct{}
func (a *Person) Move() {fmt.Println("Moving...") }
func (a *Person) Talk() {fmt.Println("Talking...") }
I can manually test each interface as follows:
func testInterfaces(entity interface{}) {
_, ok := entity.(Mover)
if ok {
fmt.Println("mover")
}
_, ok := entity.(Talker)
if ok {
fmt.Println("talker")
}
_, ok := entity.(Flyer)
if ok {
fmt.Println("flyer")
}
}
For a Person value, "mover", and "talker" will print. However, I'd rather have a function like this (non-working) one:
func testInterfaces2(entity interface{}, interfaceList type??) {
for _, inter := range interfaceList {
val, ok := entity.(inter)
if ok {
// do something with val
}
}
}
Is there a way I can achieve something like this pseudo function, maybe through the reflect package or some other means?
You could use this to get a slice of interface types.
Then, you can just check whether the Type
of your value implements the interface as in here:
interfaces := []reflect.Type{reflect.TypeOf((*Mover)(nil)).Elem(),
reflect.TypeOf((*Talker)(nil)).Elem(),
reflect.TypeOf((*Flyer)(nil)).Elem()}
p := &Person{}
t := reflect.TypeOf(p)
name := t.Elem().Name()
for _, interf := range interfaces {
if t.Implements(interf) {
fmt.Printf("%s is a %s
", name, interf.Name())
} else {
fmt.Printf("%s is NOT a %s
", name, interf.Name())
}
}
But I think the use of a Type switch is preferable if at all possible
One thing that go doesn't handle exceptionally well is generics. The Prefered way to do this is a type switch:
func testInterfaces2(entity interface{}) {
switch entity.(type) {
case Mover:
fmt.Println("mover")
case Talker:
fmt.Println("talker")
case Flyer:
fmt.Println("flyer")
default:
fmt.Println("something else")
}
}
But like val said, the way to get all of the interfaces that are implemented by a type is (a cleaned up version of val's code):
package main
import "fmt"
import "reflect"
type Mover interface { Move() }
type Talker interface { Talk() }
type Flyer interface { Fly() }
type Person struct{}
func (a *Person) Move() {fmt.Println("Moving...") }
func (a *Person) Talk() {fmt.Println("Talking...") }
func testInterfaces(entity interface{}, interfaces []reflect.Type) {
t := reflect.TypeOf(entity)
name := t.Elem().Name()
for _, interf := range interfaces {
if t.Implements(interf) {
fmt.Printf("%s is a %s
", name, interf.Name())
} else {
fmt.Printf("%s is NOT a %s
", name, interf.Name())
}
}
}
func main() {
interfaces := []reflect.Type{
reflect.TypeOf((*Mover)(nil)).Elem(),
reflect.TypeOf((*Talker)(nil)).Elem(),
reflect.TypeOf((*Flyer)(nil)).Elem(),
}
p := &Person{}
testInterfaces(p, interfaces)
}
Here it is in go play: http://play.golang.org/p/6aqMx5CQvY