我正在开发一个用Go编写的模板系统,这意味着它需要自由使用reflect
包.在这种特定情况下,我需要能够在interface{}
上动态调用一个方法.奇怪的是,只要我的数据是已知类型,我的反射逻辑就可以正常工作,但如果数据是interface{}
类型,就不行.
在下面的示例中,您可以看到main()
和Pass()
中的逻辑是相同的.唯一的区别是数据是已知类型还是interface{}
内部的已知类型
go 玩吧: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")
}
}
在执行此代码时,我们将获得以下结果
Pass() fail
startfinish
这意味着我的动态调用方法工作得很好,除非在我的对象当前为interface{}
的情况下.
相反,如果我不使用指针接收器并通过i
,那么它会按预期工作.
go 玩吧:http://play.golang.org/p/myM0UXVYzX
这让我相信,我的问题是,当I(&i
)是interface{}
时,我无法访问它的地址.我已经搜索了reflect软件包并测试了reflect.Value.Addr()
和reflect.PtrTo()
之类的东西,但我都无法按照我需要的方式工作.我的直觉是,它与一个事实有关,根据定义,interface{}
是一个参考对象.