繁体   English   中英

使用反射来遍历struct的struct成员并在其上调用方法

[英]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

您的值都不是可寻址的,因此您不能使用指针接收器在它们上调用任何方法。

如果S1S2字段不能是指针,那么如果您有指向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")
            }
        }
    }
}

https://play.golang.org/p/hHqP6WdMYqT

①如果本文未解决您的问题,请点击查看与本文相关的问题
②如果本文未解决您的问题,请向程序员专用AI小助手提问
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM