2013-09-02 14 views
7

Ich muss durch alle Felder eines Strukturtyps gehen und prüfen, ob sie eine bestimmte Schnittstelle implementieren.Prüfe, ob struct eine gegebene Schnittstelle implementiert

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

Wenn dann ein Anruf HasModels mit einer Struktur wie folgt:

type Company struct {...} 

type User struct { 
    ... 
    Company Company 
} 

HasModels(&User{}) 

Mit Unternehmen und Benutzer beide Modell implementiert; Ich bekomme f.Type.Implements (ModelType), die für das Company-Feld der User-Struktur false zurückgibt.

Das ist unerwartet, was mache ich hier falsch?

Antwort

14

Sie haben leider die wesentlichen Teile weggelassen (bitte immer vollständige Programme posten), so kann ich nur vermuten, dass das Problem in einer Methode auf einem Zeiger Empfänger definiert ist, in diesem Fall das Verhalten Ihres Codes ist erwartet. Markieren Sie dieses Beispiel und seine Ausgabe:

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


Ausgang:

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

Sie raten richtig. Ich habe gerade f.Type.Implements (modelType) zu reflect.PtrTo (f.Type) .Implements (modelType) geändert und es funktioniert perfekt. Danke für die schnelle Antwort. –

4

Es ist ein einfacher Weg, dies zu tun, die nicht reflektieren muss. Beispiel:

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

ruft die Middleware() -Methode nur in jenen Segmentelementen auf, die die Middlewarer-Schnittstelle implementieren.

+0

Außer dies bezieht sich nicht auf die OP \ s Frage, die * nicht * eine Scheibe von irgendetwas hat. Sie haben nur eine Struktur und möchten jedes Feld davon überprüfen. –

+0

Sie haben die Frage des ops nicht beantwortet, aber Sie haben einen geeigneten Weg gefunden, um zu überprüfen, ob eine Struktur eine gegebene Struktur implementiert, was genau im Titel angezeigt wird. – nevets

Verwandte Themen