2014-05-12 1 views
1

J'essaye d'écrire une fonction d'aide qui peut prendre différents types personnalisés dans Golang, mais je ne peux pas comprendre comment le faire exactement comme je le veux. Voici la situation (incidemment, je construis une API qui renvoie les objets JSON implémentant le protocole HAL, ce qui signifie simplement que les ressources et les relations sont renvoyées sous forme de liens et pas simplement d'ID).Comment écrire une fonction pour plusieurs types dans Golang?

J'ai un certain nombre de modèles dans mon application, comme étudiant, principal, école, etc ... Chacun de ces modèles a beaucoup de champs, certains mêmes, certains différents. Idéalement, j'aimerais une fonction qui peut parcourir les champs d'une structure et changer un autre champ dans la structure. Le grand défi est que ces struct peuvent être de type étudiant, directeur, école, etc ...

Modèles:

type Person struct { 
    halgo.Links 
    Id  bson.ObjectId 
    Firstname string   
    Lastname string   
    Email  string   
} 

type Student struct { 
    Person `bson:",inline"` 

    School mgo.DBRef 
} 

type School struct { 
    Id  bson.ObjectId 
    Address []string  
    Name string  
    Description string 
} 

Ensuite, je voudrais une fonction qui peut en principe prendre l'une de ces struct , parcourez les champs (en utilisant reflect) et faites quelque chose avec chaque champ.

J'ai essayé une fonction qui prend interface{} mais le problème est que vous devez taper-assert l'argument pour avoir accès à l'un des champs. Et même une fois que vous avez, vous aurez encore à écrire des fonctions individuelles pour chaque type/modèle .: de toute façon

func GenerateLinksHelper(m interface{}) { 
... 
} 

En fin de compte, je suis en train de trouver un moyen d'écrire une fonction qui prend un peu structure arbitraire et effectuer des opérations sur les champs qui peuvent ou ne peuvent pas être là.

+0

Vous pouvez avoir votre fonction 'accepter reflect.Value' et non' l'interface {} ', lui passez' reflect.ValueOf (peu importe) 'et vous pouvez parcourir les champs de struct. –

+5

Quel genre de «faire quelque chose» avez-vous en tête? Go n'est pas orienté objet, et si vous essayez de le forcer, vous aurez probablement beaucoup de maux de tête. Concentrez-vous sur un problème spécifique que vous essayez de résoudre. La réponse en général à ce genre de problème est "créer une interface", mais cela dépend de ce que vous essayez vraiment de faire pendant votre itération. refléter devrait être votre dernier choix pour les problèmes vraiment généraux (comme marshaling données arbitraires), pas votre premier choix pour la manipulation des types connus. –

+0

J'essaie de générer un objet JSON pour chaque modèle qui convertit DBRefs en liens. Par exemple, avant de renvoyer l'Etudiant en JSON, je dois parcourir ses champs, trouver des DBrefs et les convertir en liens relatifs, c'est-à-dire "school": "/ schools/123". Je voudrais un moyen général de générer ces liens, car différents modèles peuvent avoir les mêmes relations (par exemple, un directeur ou un enseignant peut aussi avoir une école). – platwp

Répondre

4

Je ne suis pas sûr de comprendre ce que vous essayez de faire, mais avec la réflexion, vous pouvez voir si un champ existe ou non et ensuite faire quelque chose avec.

Exemple dérivé de l'article 'lois de la réflexion' (http://blog.golang.org/laws-of-reflection). Jouer: http://play.golang.org/p/neU3j2MYvz

package main 

import (
    "fmt" 
    "reflect" 
) 

type T1 struct { 
    A int 
    B string 
} 

type T2 struct { 
    A int 
} 

func fct(i interface{}) { 
    s := reflect.ValueOf(i).Elem() 
    typeOfT := s.Type() 
    for i := 0; i < s.NumField(); i++ { 
     f := s.Field(i) 
     if typeOfT.Field(i).Name == "B" { 
      fmt.Printf("I am %s and I have a field B: %s\n", typeOfT.Name(), f.Interface()) 
     } 
    } 

} 

func main() { 
    t1 := T1{23, "skidoo"} 
    t2 := T2{23} 
    fct(&t1) 
    fct(&t2) 
} 
+0

Cette réponse est aussi proche de résoudre mon problème que possible, mais finalement j'essayais de faire quelque chose qui apparemment ne peut pas être fait: http://stackoverflow.com/questions/21495810/golang-how-to-do-type -assertion-for-unknown-interface – platwp

Questions connexes