2013-09-02 7 views
7

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

次に、もしそうのような構造体との通話HasModels:当社とユーザーの両方のモデルを実装して

type Company struct {...} 

type User struct { 
    ... 
    Company Company 
} 

HasModels(&User{}) 

。 User構造体のCompanyフィールドに対してfalseを返すf.Type.Implements(ModelType)が返されます。

これは予期せぬことです。私はここで間違っていますか?

答えて

14

残念ながら残念ながら(完全なプログラムを投稿してください)、ポインタの受信者に定義されたメソッドに問題があると推測できます。その場合、コードの動作はです期待される。

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

Playground


出力:

0: CompanyA main.Company -> true 
1: CompanyB *main.Company -> true 
2: DepartmentA main.Department -> false 
3: DepartmentB *main.Department -> true 
+0

あなたは正しく推測しています。私はf.Type.Implements(modelType)をreflect.PtrTo(f.Type).Implements(modelType)に変更しました。これは完全に機能します。速い答えのためのThx。 –

4

反映必要はありません。これを行う簡単な方法があります。この例で、その出力を確認してください。たとえば、

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

は、ミドルウェアインタフェースを実装するスライス要素でのみMiddleware()メソッドを呼び出します。

+0

これは、何もスライスしていないOPの質問には関係しません。彼らは構造体しか持っておらず、それぞれのフィールドをチェックしたい。 –

+0

あなたはopの質問に答えなかったのですが、構造体が構造体に構造体が実装されているかどうかを確認する適切な方法を与えました。 – nevets

関連する問題