我有一个x[, as.vector(!is.na(colSums(x))) | grepl(pattern = "name", names(x))]
# age_1 age_3 name_1 name_2
#1 0 1 NA NA
#2 1 0 NA NA
#3 1 0 NA NA
#4 0 0 NA NA
,其中包含一个或多个struct
个成员。每个成员都应实现struct
接口。
我想使用反射来迭代所有Validator
成员并调用界面的struct
方法。例如:
Validate()
运行时,输出:
恐慌:界面转换:main.T1不是main.Validator:缺少方法验证
如果我将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()
}
}
}
方法更改为接受值(而不是指针)接收器,那么它可以工作。但是,我希望使用指针接收器,因为Validate()
可能会变大。
如何更改反射代码以使用指针接收器定义方法?
我也尝试过这一行:
struct
获取指针,但然后输出:
panic:reflect.Value.Addr,无法取消值
答案 0 :(得分:2)
您的所有值都不可寻址,因此您无法通过指针接收器调用它们上的任何方法。
如果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()
}
}
答案 1 :(得分:1)
&#34; Top.S1&#34;属于&#34; T1&#34;与&#34; * T1&#34;不同类型定义&#34;验证()&#34;。
如果你改变&#34; Top.S1&#34;到&#34; * T1&#34;键入并修改字段类型检查,您的代码将正常工作。
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")
}
}
}
}