2013-09-02 18 views
7

Devo esaminare tutto il campo di un tipo di struct e controllare se implementano una determinata interfaccia.Verificare se struct implementa una determinata interfaccia

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

Quindi, se una chiamata HasModels con una struttura in questo modo:

type Company struct {...} 

type User struct { 
    ... 
    Company Company 
} 

HasModels(&User{}) 

con l'azienda e l'utente sia attuazione del Modello; Ottengo f.Type.Implements (ModelType) restituendo false per il campo Company della struttura User.

Questo è inaspettato, quindi, cosa sto facendo di sbagliato qui?

risposta

14

Hai sfortunatamente lasciato le parti essenziali (per favore pubblica sempre programmi completi), quindi posso solo supporre che il problema sia in un metodo definito su un ricevitore puntatore, nel qual caso il comportamento del tuo codice è previsto. Controllare questo esempio e la sua uscita:

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


uscita:

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

stai indovinando giusto. Ho appena modificato f.Type.Implements (modelType) per riflettere.PtrTo (f.Type) .Implements (modelType) e funziona perfettamente. Grazie per la risposta veloce. –

4

C'è un modo più semplice di fare questo che non ha bisogno riflettere. Ad esempio:

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

chiama il metodo Middleware() solo in quei elementi fetta che implementano l'interfaccia middlewarer.

+0

Tranne che questo non si riferisce alla domanda dell'OP che * non * ha una fetta di qualcosa. Hanno solo una struttura e desiderano controllare ogni campo di questo. –

+0

non hai risposto alla domanda dell'op, ma hai dato un modo corretto per verificare se una struttura implementa una determinata struttura, che è esattamente ciò che mostra nel titolo. – nevets

Problemi correlati