如何通过反射获得阴影方法?
在下面的代码中,我使用MethodByName来获取类型B
上的方法Test()
,但我也想从b.A
中获得阴影方法Test()
,所以我可以调用它们。
package main
import (
"fmt"
"reflect"
)
type A struct {}
type B struct {
A
}
func (self *A) Test() {
fmt.Println("I'm A")
}
func (self *B) Test() {
fmt.Println("I'm B")
}
func main() {
b := &B{}
b.Test() // This one shadows b.A.Test()
b.A.Test() // but its ok to call like this
// via reflection
val := reflect.ValueOf(b)
val.MethodByName("Test").Call([]reflect.Value{})
}
代码可在此获取:http://play.golang.org/p/6YPLy2dmMb
如果您有一个嵌入式结构体和阴影,您总是可以获得字段,就好像它是一个与嵌入式结构体类型同名的成员变量一样,这在b.A.Test()行中显示。
我们该怎么做?使用reflect.Value.FieldByName获取字段。你的设置有点不太好。不能在指向结构体的指针上使用FieldByName。
package main
import (
"fmt"
"reflect"
)
type A struct{}
type B struct {
A
}
func (self *A) Test() {
fmt.Println("I'm A")
}
func (self *B) Test() {
fmt.Println("I'm B")
}
func main() {
b := &B{}
b.Test()
b.A.Test()
val := reflect.ValueOf(b)
subVal := val.Elem().FieldByName("A").Addr()
subVal.MethodByName("Test").Call([]reflect.Value{})
val.MethodByName("Test").Call([]reflect.Value{})
}
如所见,它有点难看。首先需要调用Elem
来获得val
指向的值,然后获得字段,然后获得指向该字段的指针,因为A.Test
实际上在(*A)
上,而不是A
。虽然Go指针通常是透明的,但不幸的是,它不适用于反射,因此您必须自己执行所有显式寻址/解引用,但如果您了解指针,则非常简单。
编辑:Playground链接到上面的代码
当你将一个结构体嵌入到另一个结构体中,比如a嵌入到B中,你只是在结构体B中创建了一个名为a的类型为a的字段。作为语法上的方便,你可以直接在B上调用a上的方法,但在语义上没有关于"阴影方法"的特殊事情;它们只是碰巧在结构体内部的a型值的方法。
你只需要用反射API模仿你的b.A.Test()
。不好的是反射不能执行纯Go所做的那种糖,所以你需要模仿的是(&((*b).A)).Test()
。
val.Elem(). // Go to *B
FieldByName("A"). // Find field named A
Addr(). // Take its address, since Test has a method receiver of type *A
MethodByName("Test"). // Find its method Test
Call([]reflect.Value{})
更新代码:http://play.golang.org/p/67xc66ULFz
(顺便说一下,调用方法接收者"self"在Go中不是习惯用法。)