[英]Using reflection to iterate over struct's struct members and calling a method on it
I have a struct
that has one or more struct
members. 我有一个
struct
具有一个或多个struct
的成员。 Each member is expected to implement a Validator
interface. 每个成员
Validator
实现一个Validator
接口。
I want to use reflection to iterate over all struct
members and call the interface's Validate()
method. 我想使用反射遍历所有
struct
成员并调用接口的Validate()
方法。 For example: 例如:
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()
}
}
}
When run, it outputs: 运行时,它输出:
panic: interface conversion: main.T1 is not main.Validator: missing method Validate
紧急:接口转换:main.T1不是main.Validator:缺少方法Validate
If I change the Validate()
methods to accept value (rather than pointer) receivers, then it works. 如果我将
Validate()
方法更改为接受值(而不是指针)接收器,则它将起作用。 However, I want to use pointer receivers since the struct
s may grow to be large. 但是,由于
struct
可能会变大,因此我想使用指针接收器。
How can I change the reflection code to work where the methods are defined taking pointer receivers? 如何在使用指针接收器定义方法的地方更改反射代码?
I also tried using this line: 我也尝试使用此行:
validator := f.Addr().Interface().(Validator)
to get a pointer, but it then outputs: 得到一个指针,但是它输出:
panic: reflect.Value.Addr of unaddressable value
恐慌:无法确定值的reflect.Value.Addr
None of your values are addressable, so you can't call any methods on them with pointer receivers. 您的值都不是可寻址的,因此您不能使用指针接收器在它们上调用任何方法。
If the S1
and S2
fields can't be pointers, you can still address them if you have a pointer to the Top
struct: 如果
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" is of type "T1" and is different from "*T1" type defined "Validate()". “ Top.S1”的类型为“ T1”,与定义为“ Validate()”的“ * T1”类型不同。
If you change "Top.S1" to "*T1" type and modify the field type checking, your code will work properly. 如果将“ 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")
}
}
}
}
https://play.golang.org/p/hHqP6WdMYqT https://play.golang.org/p/hHqP6WdMYqT
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.