簡體   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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM