136 votes

Convertir l'interface{} en int

J'essaie d'obtenir une valeur à partir d'un JSON et de la convertir en int, mais cela ne fonctionne pas, et je ne sais pas comment le faire correctement.

Voici le message d'erreur :

...cannot convert val (type interface {}) to type int: need type assertion

Et le code :

    var f interface{}
    err = json.Unmarshal([]byte(jsonStr), &f)
    if err != nil {
        utility.CreateErrorResponse(w, "Error: failed to parse JSON data.")
        return
    }

    m := f.(map[string]interface{})

    val, ok := m["area_id"]
    if !ok {
        utility.CreateErrorResponse(w, "Error: Area ID is missing from submitted data.")
        return
    }

    fmt.Fprintf(w, "Type = %v", val)   // <--- Type = float64
    iAreaId := int(val)                // <--- Error on this line.
    testName := "Area_" + iAreaId      // not reaching here

255voto

zzzz Points 23017

Au lieu de

iAreaId := int(val)

vous voulez un affirmation de type :

iAreaId := val.(int)
iAreaId, ok := val.(int) // Alt. non panicking version 

La raison pour laquelle vous ne pouvez pas convertir une valeur typée interface sont ces règles dans les parties de specs référencées :

Les conversions sont des expressions de la forme T(x)T est un type et x est une expression qui peut être convertie en type T.

...

Une valeur non constante x peut être convertie en type T dans l'un de ces cas :

  1. x est assignable à T.
  2. Le type de x et T ont des types sous-jacents identiques.
  3. Le type de x et T sont des types pointeurs non nommés et leurs types de base pointeurs ont des types sous-jacents identiques.
  4. Le type de x et T sont tous deux des types entiers ou à virgule flottante.
  5. Le type de x et T sont tous deux des types complexes.
  6. x est un entier ou une tranche d'octets ou de runes et T est un type de chaîne de caractères.
  7. x est une chaîne de caractères et T est une tranche d'octets ou de runes.

Mais

iAreaId := int(val)

est no l'un des cas 1.-7.

49voto

Mujibur Points 736

Je suppose : Si vous avez envoyé la valeur JSON par le navigateur, alors tout nombre que vous avez envoyé sera du type float64, donc vous ne pouvez pas obtenir la valeur directement int dans golang.

Ainsi que la conversion comme :

//As that says: 
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64

var iAreaId int = int(val.(float64))

De cette façon, vous pouvez obtenir la valeur exacte que vous vouliez.

5voto

openwonk Points 7520

Je suis tout à fait d'accord avec zzzz 's affirmation de type et je préfère nettement cette façon de faire aux autres. Cela dit, voici ce que j'ai dû faire lorsque la méthode préférée n'a pas fonctionné... (longue histoire liée à la sérialisation croisée des données). Vous pouvez même enchaîner ceci dans un switch déclaration avec case errInt == nil et autres expressions similaires.

package main

import "fmt"
import "strconv"

func main() {
    var v interface{}
    v = "4"

    i, errInt := strconv.ParseInt(v.(string), 10, 64)

    if errInt == nil {
        fmt.Printf("%d is a int", i)
        /* do what you wish with "i" here */
    }
}

Comme je l'ai dit plus haut, essayez affirmation de type avant d'essayer de cette façon.

5voto

openwonk Points 7520

Ajouter une autre réponse qui utilise switch ... Il existe des exemples plus complets, mais celui-ci vous donnera une idée.

En exemple, t devient le type de données spécifié dans chaque case portée. Notez que vous devez fournir un case pour un seul type à la fois, sinon t reste un interface .

package main

import "fmt"

func main() {
    var val interface{} // your starting value
    val = 4

    var i int // your final value

    switch t := val.(type) {
    case int:
        fmt.Printf("%d == %T\n", t, t)
        i = t
    case int8:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case int16:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case int32:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case int64:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case bool:
        fmt.Printf("%t == %T\n", t, t)
        // // not covertible unless...
        // if t {
        //  i = 1
        // } else {
        //  i = 0
        // }
    case float32:
        fmt.Printf("%g == %T\n", t, t)
        i = int(t) // standardizes across systems
    case float64:
        fmt.Printf("%f == %T\n", t, t)
        i = int(t) // standardizes across systems
    case uint8:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case uint16:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case uint32:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case uint64:
        fmt.Printf("%d == %T\n", t, t)
        i = int(t) // standardizes across systems
    case string:
        fmt.Printf("%s == %T\n", t, t)
        // gets a little messy...
    default:
        // what is it then?
        fmt.Printf("%v == %T\n", t, t)
    }

    fmt.Printf("i == %d\n", i)
}

2voto

Carson Arucard Points 334

Vous pouvez utiliser refléter pour vous aider à déterminer le type et ensuite convertir.

func i2num(a interface{}) (interface{}, error) { // interface to number
    aValue := reflect.ValueOf(a)
    switch aValue.Kind() {
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return aValue.Int(), nil
    case reflect.Float32, reflect.Float64:
        return aValue.Float(), nil
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
        return aValue.Uint(), nil
    case reflect.Bool:
        if a == true {
            return 1, nil
        }
        return 0, nil
    case reflect.String:
        return strconv.ParseFloat(aValue.String(), 64)
    default:
        return nil, errors.New("type error")
    }
}

Go Playground

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