我需要遍历struct类型的所有字段并检查它们是否实现了给定的接口.
type Model interface {...}
func HasModels(m Model) {
s := reflect.ValueOf(m).Elem()
t := s.Type()
modelType := reflect.TypeOf((*Model)(nil)).Elem()
for i := 0; i < s.NumField(); i++ {
f := t.Field(i)
fmt.Printf("%d: %s %s -> %s\n", i, f.Name, f.Type, f.Type.Implements(modelType))
}
}
Run Code Online (Sandbox Code Playgroud)
然后,如果调用具有如下结构的HasModels:
type Company struct {...}
type User struct {
...
Company Company
}
HasModels(&User{})
Run Code Online (Sandbox Code Playgroud)
公司和用户都实施模型; 我得到f.Type.Implements(ModelType)为User结构的Company字段返回false.
这是出乎意料的,所以,我在这里做错了什么?
zzz*_*zzz 18
遗憾的是,遗漏了必要的部分(请总是发布完整的程序),所以我只能猜测问题出在指针接收器上定义的方法中,在这种情况下,代码的行为是预期的.检查此示例及其输出:
package main
import (
"fmt"
"reflect"
)
type Model interface {
m()
}
func HasModels(m Model) {
s := reflect.ValueOf(m).Elem()
t := s.Type()
modelType := reflect.TypeOf((*Model)(nil)).Elem()
for i := 0; i < s.NumField(); i++ {
f := t.Field(i)
fmt.Printf("%d: %s %s -> %t\n", i, f.Name, f.Type, f.Type.Implements(modelType))
}
}
type Company struct{}
func (Company) m() {}
type Department struct{}
func (*Department) m() {}
type User struct {
CompanyA Company
CompanyB *Company
DepartmentA Department
DepartmentB *Department
}
func (User) m() {}
func main() {
HasModels(&User{})
}
Run Code Online (Sandbox Code Playgroud)
输出:
0: CompanyA main.Company -> true
1: CompanyB *main.Company -> true
2: DepartmentA main.Department -> false
3: DepartmentB *main.Department -> true
Run Code Online (Sandbox Code Playgroud)
有一种更简单的方法可以做到这一点,不需要反思.例如:
type middlewarer interface {Middleware() negroni.Handler}
for _, controller := range ctrls {
if m, ok := interface{}(controller).(middlewarer); ok {
n.Use(m.Middleware())
}
}
Run Code Online (Sandbox Code Playgroud)
仅在实现中间件接口的那些切片元素中调用Middleware()方法.