I'm working on a templating system written in Go, which means it requires liberal use of the reflect
package. In this specific circumstance I need to be able to dynamically call a method on an interface{}
. The oddity is that my reflection logic works fine as long as my data is of a known type, but not if the data is of type interface{}
.
The the following example you can see that the logic in main()
and Pass()
is identical. The only difference is whether the data is a known type or a known type inside an interface{}
Go Play: http://play.golang.org/p/FTP3wgc0sZ
package main
import (
"fmt"
"reflect"
)
type Test struct {
Start string
}
func (t *Test) Finish() string {
return t.Start + "finish"
}
func Pass(i interface{}) {
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("Pass() fail")
}
}
func main() {
i := Test{Start: "start"}
Pass(i)
_, ok := reflect.TypeOf(&i).MethodByName("Finish")
if ok {
fmt.Println(reflect.ValueOf(&i).MethodByName("Finish").Call([]reflect.Value{})[0])
} else {
fmt.Println("main() fail")
}
}
Upon executing this code we get the following result
Pass() fail
startfinish
Which means that my methodology for dynamically calling a method works fine except in a scenario when my object is currently in an interface{}
.
If instead I do not use a pointer receiver and pass i
then it works as expected.
Go Play: http://play.golang.org/p/myM0UXVYzX
This leads me to believe that my problem is that I cannot access the address of i (&i
) when it is an interface{}
. I've scoured the reflect package and tested things such as reflect.Value.Addr()
and reflect.PtrTo()
but I could not get either to work the way I needed. My hunch is that it has something to do with the fact that an interface{}
is by definition a reference object.