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