2 votes

Comment obtenir une valeur de structure sur une interface inconnue ?

Si j'ai un struct et que je veux obtenir sa clé, mais qu'il est actuellement du type interface{} Comment je fais ça ?

Actuellement, j'obtiens l'erreur de compilation suivante :

invalid operation: d[label] (index of type interface {})

Jouez : http://play.golang.org/p/PLr91d55GX

package main

import "fmt"
import "reflect"

type Test struct {
    s string
}

func main() {
    test := Test{s: "blah"}
    fmt.Println(getProp(test, "s"))
}

func getProp(d interface{}, label string) (interface{}, bool) {
    switch reflect.TypeOf(d).Kind() {
    case reflect.Struct:
        _, ok := reflect.TypeOf(d).FieldByName(label)
        if ok {
                    // errors here because interface{} doesn't have index of type 
            return d[label], true
        } else {
            return nil, false
        }
    }
}

Dois-je vraiment faire l'énoncé massif de cas pour chaque type différent et appeler l'analyse reflétée ? reflect.ValueOf(x).String() etc ? J'espère qu'il existe un moyen plus élégant.

2voto

nos Points 102226

Vous pourriez le faire, mais je pense que cela ne fonctionnera que si votre membre de structure s était un champ exporté (c'est-à-dire utiliser une majuscule S dans votre exemple)

func getProp(d interface{}, label string) (interface{}, bool) {
    switch reflect.TypeOf(d).Kind() {
    case reflect.Struct:
        v := reflect.ValueOf(d).FieldByName(label)
             return v.Interface(), true
    }
   return nil, false
}

(+ un peu plus de gestion des erreurs)

0voto

Derek Points 1558

Je ne sais pas exactement ce que vous recherchez, mais il existe un moyen légèrement plus simple de rechercher les types interface{}. Dans votre cas, vous pourriez utiliser :

switch val := d.(type) {
  case Test:
    fmt.Println(d.s)
}

Évidemment, je ne fais pas la même chose que vous, mais l'idée est que vous pouvez vérifier le type avec "d.(type)", et une fois que "case Test :" détermine que c'est une structure de votre type Test, vous pouvez y accéder comme tel.

Malheureusement, cela ne résout pas le problème de l'accès à la valeur dans la structure par l'étiquette, mais c'est au moins une manière plus élégante de déterminer le type, et @nos montre comment faire cela avec

v := reflect.ValueOf(d).FieldByName(label)
return v.Interface(), true

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X