webentwicklung-frage-antwort-db.com.de

Konvertiere Schnittstelle {} in int

Ich versuche, einen Wert von einem JSON zu erhalten und in int umzuwandeln, aber es funktioniert nicht und ich weiß nicht, wie ich es richtig machen soll.

Hier ist die Fehlermeldung:

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

Und der 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
77
Nick

Anstatt

iAreaId := int(val)

sie möchten eine Typ-Zusicherung :

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

Der Grund dafür, dass Sie convert einen von der Schnittstelle eingegebenen Wert nicht konvertieren können, sind die folgenden Regeln in den referenzierten Spezifikationsbestandteilen:

Konvertierungen sind Ausdrücke der Form T(x), wobei T ein Typ und x ein Ausdruck ist, der in Typ T konvertiert werden kann.

...

Ein nicht konstanter Wert x kann in allen folgenden Fällen in den Typ T konvertiert werden:

  1. x ist T. zuweisbar.
  2. x-Typ und T haben identische zugrunde liegende Typen.
  3. der Typ x und der Typ T sind unbenannte Zeigertypen, und ihre Zeiger-Basistypen haben identische zugrunde liegende Typen.
  4. x-Typ und T sind beide Ganzzahl- oder Gleitkommatypen.
  5. x-Typ und T sind beide komplexe Typen.
  6. x ist eine ganze Zahl oder ein Slice von Bytes oder Runen und T ist ein String-Typ.
  7. x ist eine Zeichenfolge und T ist ein Teil von Bytes oder Runen.

Aber

iAreaId := int(val)

ist nicht einer der Fälle 1.-7.

144
zzzz

Ich gehe davon aus: Wenn Sie den JSON-Wert über einen Browser gesendet haben, wird jede beliebige Zahl, die Sie gesendet haben, vom Typ float64 sein, so dass Sie den Wert nicht direkt in golang erhalten können.

So macht die Konvertierung:

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

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

Auf diese Weise können Sie genau wissen, was Sie wollten.

20
Mujibur

Ich stimme von ganzem Herzen mit zzzz 's Typbehauptung überein und ich ziehe diesen Weg anderen vor. Das heißt, hier ist, was ich tun musste, wenn die bevorzugte Methode nicht funktioniert hat ... (lange Geschichte im Zusammenhang mit der Cross-Serialisierung von Daten). Sie können dies sogar in eine switch -Anweisung mit case errInt == nil Und ähnlichen Ausdrücken verketten.

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 */
    }
}

Versuchen Sie, wie oben erwähnt, zunächst Geben Sie assertion ein, bevor Sie dies versuchen.

3
openwonk

Hinzufügen einer weiteren Antwort, die switch... verwendet Es gibt umfangreichere Beispiele, aber dies gibt Ihnen die Idee. 

Im Beispiel wird t zum angegebenen Datentyp innerhalb jedes case-Bereichs. Beachten Sie, dass Sie eine case nur für einen Typ eines Typs angeben müssen, andernfalls bleibt t eine 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)
}
1
openwonk

Sie müssen eine Typüberprüfung durchführen, um Ihre Schnittstelle {} in einen int-Wert zu konvertieren.

iAreaId := val.(int)
iAreaId, ok := val.(int)

Weitere Informationen sind verfügbar .

0
Kabeer Shaikh

Ich habe eine Bibliothek geschrieben, die bei Typkonvertierungen helfen kann https://github.com/KromDaniel/jonson

js := jonson.New([]interface{}{55.6, 70.8, 10.4, 1, "48", "-90"})

js.SliceMap(func(jsn *jonson.JSON, index int) *jonson.JSON {
    jsn.MutateToInt()
    return jsn
}).SliceMap(func(jsn *jonson.JSON, index int) *jonson.JSON {
    if jsn.GetUnsafeInt() > 50{
        jsn.MutateToString()
    }
    return jsn
}) // ["55","70",10,1,48,-90]
0
Daniel Krom

So einfach habe ich das gemacht. Nicht der beste Weg, aber der einfachste Weg, ich weiß, wie.

import "fmt"

func main() {
    fmt.Print(addTwoNumbers(5, 6))
}

func addTwoNumbers(val1 interface{}, val2 interface{}) int {
    op1, _ := val1.(int)
    op2, _ := val2.(int)

    return op1 + op2
}
0
Mo-Gang