19

我需要遍历结构类型的所有字段并检查它们是否实现了给定的接口。

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)) 
    }       
}

然后,如果调用 HasModels 的结构如下:

type Company struct {...}

type User struct {
    ...
    Company Company
}

HasModels(&User{})

公司和用户都实施模型;我得到 f.Type.Implements(ModelType) 为 User 结构的 Company 字段返回 false。

这是出乎意料的,那么,我在这里做错了什么?

4

3 回答 3

32

不幸的是,您遗漏了基本部分(请始终发布完整的程序),所以我只能猜测问题出在指针接收器上定义的方法中,在这种情况下,您的代码的行为预期的。检查此示例及其输出:

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{})
}

操场


输出:

0: CompanyA main.Company -> true
1: CompanyB *main.Company -> true
2: DepartmentA main.Department -> false
3: DepartmentB *main.Department -> true
于 2013-09-02T10:45:29.440 回答
11

有一种不需要反思的更简单的方法。例如:

type middlewarer interface {Middleware() negroni.Handler}
for _, controller := range ctrls {
    if m, ok := interface{}(controller).(middlewarer); ok {
        n.Use(m.Middleware())
    }
}

仅在那些实现中间件接口的切片元素中调用 Middleware() 方法。

于 2015-05-02T17:41:47.077 回答
0

如果变量不是接口,则将其设为一个。

foo := interface{}(yourVar)

然后你可以检查它是否实现了你感兴趣的接口。

bar, ok := foo.(yourInterface)
if !ok {
    // handle the case where it doesn't match the interface
}
bar.methodOnYourInterface()

这是一个更充实的示例的游乐场链接

于 2021-12-01T19:08:13.187 回答