[英]Using reflection to iterate over struct's struct members and calling a method on it
我有一个struct
具有一个或多个struct
的成员。 每个成员Validator
实现一个Validator
接口。
我想使用反射遍历所有struct
成员并调用接口的Validate()
方法。 例如:
package main
import "fmt"
import "reflect"
type Validator interface {
Validate()
}
type T1 struct {
S string
}
func (p *T1) Validate() {
fmt.Println("HERE 1")
}
type T2 struct {
S string
}
func (p *T2) Validate() {
fmt.Println("HERE 2")
}
type Top struct {
S1 T1
S2 T2
}
func main() {
var t Top
r := reflect.ValueOf(t)
for i := 0; i < r.NumField(); i++ {
f := r.Field(i)
if f.Kind() == reflect.Struct {
validator := f.Interface().(Validator)
validator.Validate()
}
}
}
运行时,它输出:
紧急:接口转换:main.T1不是main.Validator:缺少方法Validate
如果我将Validate()
方法更改为接受值(而不是指针)接收器,则它将起作用。 但是,由于struct
可能会变大,因此我想使用指针接收器。
如何在使用指针接收器定义方法的地方更改反射代码?
我也尝试使用此行:
validator := f.Addr().Interface().(Validator)
得到一个指针,但是它输出:
恐慌:无法确定值的reflect.Value.Addr
您的值都不是可寻址的,因此您不能使用指针接收器在它们上调用任何方法。
如果S1
和S2
字段不能是指针,那么如果您有指向Top
结构的指针,您仍然可以解决它们:
r := reflect.ValueOf(&t).Elem()
for i := 0; i < r.NumField(); i++ {
f := r.Field(i)
if f.Kind() == reflect.Struct {
validator := f.Addr().Interface().(Validator)
validator.Validate()
}
}
“ Top.S1”的类型为“ T1”,与定义为“ Validate()”的“ * T1”类型不同。
如果将“ Top.S1”类型更改为“ * T1”类型并修改字段类型检查,则代码将正常工作。
type Top struct {
S1 *T1
S2 *T2
}
func main() {
t := Top{&T1{}, &T2{}}
r := reflect.ValueOf(t)
for i := 0; i < r.NumField(); i++ {
f := r.Field(i)
if f.Kind() == reflect.Ptr && f.Elem().Kind() == reflect.Struct {
validator, ok := f.Interface().(Validator)
if ok {
validator.Validate()
} else {
fmt.Println("not ok")
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.