0

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

2
  • The usual way to handle generic-like functions in Go is through interfaces. Your example seems fairly abstract though, so it is hard to give specific advice. Commented Feb 25, 2014 at 11:38
  • I'm having a hard time understanding what you're trying to do. Could you provide a similar example in a language w/ generics (like C#)? Commented Feb 25, 2014 at 19:04

1 Answer 1

1
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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.