Comment déterminer le type “réel” d’une interface {} valeur?

Je n’ai pas trouvé de ressource pour utiliser les types interface{} . Par exemple

 package main import "fmt" func weirdFunc(i int) interface{} { if i == 0 { return "zero" } return i } func main() { var i = 5 var w = weirdFunc(5) // this example works! if tmp, ok := w.(int); ok { i += tmp } fmt.Println("i =", i) } 

Connaissez-vous une bonne introduction à l’utilisation de l’ interface{} de Go interface{} ?

questions spécifiques:

  • comment puis-je obtenir le “vrai” type de w?
  • existe-t-il un moyen d’obtenir la représentation sous forme de chaîne d’un type?
  • existe-t-il un moyen d’utiliser la représentation sous forme de chaîne d’un type pour convertir une valeur?

Votre exemple fonctionne. Voici une version simplifiée.

 package main import "fmt" func weird(i int) interface{} { if i < 0 { return "negative" } return i } func main() { var i = 42 if w, ok := weird(7).(int); ok { i += w } if w, ok := weird(-100).(int); ok { i += w } fmt.Println("i =", i) } Output: i = 49 

Il utilise des assertions de type .

Vous pouvez également faire des commutateurs de type:

 switch v := myInterface.(type) { case int: // v is an int here, so eg v + 1 is possible. fmt.Printf("Integer: %v", v) case float64: // v is a float64 here, so eg v + 1.0 is possible. fmt.Printf("Float64: %v", v) case ssortingng: // v is a ssortingng here, so eg v + " Yeah!" is possible. fmt.Printf("Ssortingng: %v", v) default: // And here I'm feeling dumb. ;) fmt.Printf("I don't know, ask stackoverflow.") } 

Vous pouvez utiliser la reflection ( reflect.TypeOf() ) pour obtenir le type de quelque chose, et la valeur reflect.TypeOf() Type ) a une représentation sous forme de chaîne (méthode Ssortingng ) que vous pouvez imprimer.

Voici un exemple de décodage d’une carte générique utilisant à la fois le commutateur et la reflection, donc si vous ne correspondez pas au type, utilisez la reflection pour le comprendre, puis ajoutez le type la prochaine fois.

 var data map[ssortingng]interface {} ... for k, v := range data { fmt.Printf("pair:%s\t%s\n", k, v) switch t := v.(type) { case int: fmt.Printf("Integer: %v\n", t) case float64: fmt.Printf("Float64: %v\n", t) case ssortingng: fmt.Printf("Ssortingng: %v\n", t) case bool: fmt.Printf("Bool: %v\n", t) case []interface {}: for i,n := range t { fmt.Printf("Item: %v= %v\n", i, n) } default: var r = reflect.TypeOf(t) fmt.Printf("Other:%v\n", r) } } 

Les commutateurs de type peuvent également être utilisés avec des éléments de reflection:

 var str = "hello!" var obj = reflect.ValueOf(&str) switch obj.Elem().Interface().(type) { case ssortingng: log.Println("obj contains a pointer to a ssortingng") default: log.Println("obj contains something else") } 

Je vais proposer un moyen de renvoyer un booléen basé sur le passage d’un argument de type Kind à un récepteur de type local (car je n’ai rien trouvé de tel).

Tout d’abord, nous déclarons notre type anonyme de type reflect.Value:

 type AnonymousType reflect.Value 

Ensuite, nous ajoutons un générateur pour notre type local AnonymousType qui peut prendre n’importe quel type de potentiel (en tant qu’interface):

 func ToAnonymousType(obj interface{}) AnonymousType { return AnonymousType(reflect.ValueOf(obj)) } 

Ensuite, nous ajoutons une fonction pour notre structure AnonymousType qui s’affirme contre un reflet.

 func (a AnonymousType) IsA(typeToAssert reflect.Kind) bool { return typeToAssert == reflect.Value(a).Kind() } 

Cela nous permet d’appeler le suivant:

 var f float64 = 3.4 anon := ToAnonymousType(f) if anon.IsA(reflect.Ssortingng) { fmt.Println("Its A Ssortingng!") } else if anon.IsA(reflect.Float32) { fmt.Println("Its A Float32!") } else if anon.IsA(reflect.Float64) { fmt.Println("Its A Float64!") } else { fmt.Println("Failed") } 

Peut voir une version de travail plus longue ici: https://play.golang.org/p/EIAp0z62B7