英文:
Check if struct implements a given interface
问题
我需要遍历一个结构体类型的所有字段,并检查它们是否实现了给定的接口。
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{})
Company和User都实现了Model接口,但是对于User结构体的Company字段,f.Type.Implements(ModelType)返回false。
这是意外的结果,所以我在这里做错了什么?
英文:
I need to walk through all the field of a struct type and check if they implements a given interface.
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))
}
}
Then, if a call HasModels with a struct like so :
type Company struct {...}
type User struct {
...
Company Company
}
HasModels(&User{})
With Company and User both implementing Model; I get f.Type.Implements(ModelType) returning false for the Company field of the User struct.
This is unexpected, so, what Am I doing wrong here ?
答案1
得分: 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
英文:
You've unfortunately left out the essential parts (please always post complete programs), so I can only guess that the problem is in a method defined on a pointer receiver, in which case the behavior of your code is expected. Check this example and its output:
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{})
}
Output:
0: CompanyA main.Company -> true
1: CompanyB *main.Company -> true
2: DepartmentA main.Department -> false
3: DepartmentB *main.Department -> true
答案2
得分: 12
有一种更简单的方法可以做到这一点,而不需要使用 reflect。例如:
type middlewarer interface {Middleware() negroni.Handler}
for _, controller := range ctrls {
if m, ok := interface{}(controller).(middlewarer); ok {
n.Use(m.Middleware())
}
}
只在实现了 middlewarer 接口的切片元素中调用 Middleware() 方法。
英文:
There's an easier way of doing this that doesn't need reflect. For example:
type middlewarer interface {Middleware() negroni.Handler}
for _, controller := range ctrls {
if m, ok := interface{}(controller).(middlewarer); ok {
n.Use(m.Middleware())
}
}
calls the Middleware() method only in those slice elements that implement the middlewarer interface.
答案3
得分: 2
如果变量不是一个接口类型,可以将其转换为接口类型。
foo := interface{}(yourVar)
然后你可以检查它是否实现了你感兴趣的接口。
bar, ok := foo.(yourInterface)
if !ok {
// 处理不匹配接口的情况
}
bar.methodOnYourInterface()
英文:
If the variable is not an interface, make it one.
foo := interface{}(yourVar)
Then you can check if it implements the interface you're interested in.
bar, ok := foo.(yourInterface)
if !ok {
// handle the case where it doesn't match the interface
}
bar.methodOnYourInterface()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论