Reputation: 36101
I'm trying to write a function that will process a certain type of objects and call a certain method passed as one of the args. Since there's no inheritance or generics, I'm using embedding. (I can't use interfaces as you can only define methods in them, and I need struct fields as well).
I'm new at Go, so I'm definitely doing something wrong. Here's a simplified version of my code:
http://play.golang.org/p/r0mtDXtmWc
package main
import "fmt"
import "reflect"
type Animal struct {
Type string
}
type Dog struct {
Animal
}
type Cat struct {
Animal
}
func (d *Dog) SayWoof() {
fmt.Println("WOOF")
}
func (c *Cat) SayMeouw() {
fmt.Println("MEOUW")
}
func CallMethod(animal interface{}, baseAnimal *Animal, methodName string) {
fmt.Println("Animal type: ", baseAnimal.Type)
method := reflect.ValueOf(animal).MethodByName(methodName)
if !method.IsValid() {
return
}
method.Call([]reflect.Value{})
}
func main() {
dog := &Dog{}
dog.Type = "Dog" // for some reason dog := &Dog{Type: "Dog"} doesn't compile
cat := &Cat{}
cat.Type = "Cat"
CallMethod(dog, &dog.Animal, "SayWoof")
CallMethod(cat, &cat.Animal, "SayMeouw")
}
output:
Animal type: Dog
WOOF
Animal type: Cat
MEOUW
This code works, but I basically need to pass an object twice: first an interface to call a method dynamically and then the embedded ("parent") object to get access to its fields.
I would much rather have something like
func CallMethod(animal Animal, methodName string)
but then if cast a Dog
object to an Animal
like this:
CallMethod(dog.Animal, "SayWoof")
it obviously won't work as there's no "SayWoof" method defined in Animal.
So the question is: is there a way to pass a child object to a function once and have access to all its reflection data?
Thanks
Upvotes: 0
Views: 313
Reputation: 7397
package main
import "fmt"
type Animal interface {
Speak()
}
type Dog struct {
}
type Cat struct {
}
func (d *Dog) Speak() {
fmt.Println("Woof")
}
func (c *Cat) Speak() {
fmt.Println("Meow")
}
func Speaketh(a Animal) {
a.Speak()
}
func main() {
dog := Dog{}
cat := Cat{}
Speaketh(&dog)
Speaketh(&cat)
}
How exactly would you expect a language with generics to solve your problem anyway? That's an honest question. With different function names you want to call "SayMeow" and "SayWoof", no type agnostic data structure is going to help you magically call the right thing.
Upvotes: 1