140 votes

Comment déterminer le type "réel" d'une valeur d'interface{} ?

Je n'ai pas trouvé de bonne ressource pour utiliser interface{} types. 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'algorithme de Go ? interface{} ?

des questions spécifiques :

  • comment obtenir le "vrai" Type of w ?
  • Existe-t-il un moyen d'obtenir la représentation en chaîne d'un type ?
  • existe-t-il un moyen d'utiliser la représentation en chaîne d'un type pour convertir une valeur ?

147voto

Mue Points 2469

Vous pouvez également effectuer des changements de type :

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

0 votes

Dans l'exemple, comment puis-je convertir var w en int ?

3 votes

L'exemple de Mue fait la même chose, mais dans un commutateur de type au lieu d'une instruction if. Dans le "case int", "v" sera un entier. Dans le "case float64", "v" sera un float64, etc.

0 votes

Exact. J'avais oublié la syntaxe var.(type), qui est sournoise et cool.

112voto

peterSO Points 25725

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 Assertions de type .

0 votes

Vous avez tout à fait raison ! merci ! avez-vous des idées sur les représentations des types par des chaînes de caractères ?

16 votes

Vérifiez reflect.TypeOf .

0 votes

@DmitriGoldring Cela répond au moins à la question posée dans le titre du sujet. Cette réponse ne l'est pas. Merci beaucoup.

63voto

newacct Points 42530

Vous pouvez utiliser la réflexion ( reflect.TypeOf() ) pour obtenir le type de quelque chose, et la valeur qu'il donne ( Type ) a une représentation sous forme de chaîne ( String ) que vous pouvez imprimer.

10 votes

Et si vous voulez juste obtenir une chaîne de caractères ou un type (par exemple pour l'impression dans le bloc par défaut d'un lien de commutation de type en La réponse de Mue vous pouvez simplement utiliser fmt au lieu d'utiliser directement le format "%T" de l'UE. reflect .

18voto

h4ck3rm1k3 Points 961

Voici un exemple de décodage d'une carte générique utilisant à la fois l'interrupteur et la réflexion. Si le type ne correspond pas, utilisez la réflexion pour le déterminer et ajoutez le type la prochaine fois.

var data map[string]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 string:
        fmt.Printf("String: %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)             
    }
}

8voto

Nikolai Koudelia Points 241

Les interrupteurs de type peuvent également être utilisés avec des éléments de réflexion :

var str = "hello!"
var obj = reflect.ValueOf(&str)

switch obj.Elem().Interface().(type) {
case string:
    log.Println("obj contains a pointer to a string")
default:
    log.Println("obj contains something else")
}

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