{} Arayüzünü int'e dönüştür


102

Bir JSON'dan bir değer elde etmeye ve onu int'e çevirmeye çalışıyorum ama işe yaramıyor ve nasıl düzgün yapacağımı bilmiyorum.

İşte hata mesajı:

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

Ve kod:

    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

Yanıtlar:


206

Onun yerine

iAreaId := int(val)

bir tür iddiası istiyorsunuz :

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

Arabirime yazılan bir değeri dönüştürememenizin nedeni , referans verilen özellikler bölümlerindeki şu kurallardır:

Dönüşüm formunun ifadelerdir türü olup, T. tip dönüştürülebilir bir ifadedirT(x)Tx

...

Sabit olmayan bir x değeri, aşağıdaki durumlardan herhangi birinde T türüne dönüştürülebilir:

  1. x, T'ye atanabilir.
  2. x'in türü ve T'nin temel türleri aynıdır.
  3. x'in türü ve T, adsız işaretçi türleridir ve işaretçi temel türleri aynı temel türlere sahiptir.
  4. x'in türü ve T'nin her ikisi de tam sayı veya kayan nokta türleridir.
  5. x'in türü ve T'nin her ikisi de karmaşık türlerdir.
  6. x bir tamsayı veya bir bayt veya run dilimi ve T bir dize türüdür.
  7. x bir dizedir ve T bir bayt veya run dilimi.

Fakat

iAreaId := int(val)

herhangi bir durum değildir 1.-7.


İyi cevap! Dil spesifikasyonu her zaman bir cevap aramak için en iyi yerdir!
Hot.PxL

Teşekkürler. bu güzel bir cevap.
Muktadir

32

Varsayıyorum: JSON değerini tarayıcı aracılığıyla gönderdiyseniz, gönderdiğiniz herhangi bir sayı float64 olacaktır, böylece doğrudan golang'da int değerini alamazsınız.

Öyleyse dönüşüm şöyle yapın:

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

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

Bu şekilde, istediğinizi tam olarak elde edebilirsiniz.


% 100 haklısınız @Mujibur, ancak JSON özelliklerinde tamsayı türü olduğu için herhangi bir nedenle
kamal

1
@kamal bunun nedeni JSON'un Javascript sözdizimini ve tanımlarını kullanmasıdır. JavaScript yalnızca 64 bit kayan nokta sayılarını destekler. Ref # javascript.info/number
Mujibur

4

Kullanan başka bir cevap eklemek switch... Orada daha kapsamlı örnekler var, ama bu size fikri verecektir.

Örneğin, ther casekapsamda belirtilen veri türü haline gelir . caseBir türde yalnızca bir tür için bir sağlamanız gerektiğini , aksi takdirde tbir 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)
}

İçin case string, kullanabilir strconv.ParseFloat(t, 32)ve ardından sonucu birint
JVE999

3

Heartedly katılıyorum zzzz 'ın tipi iddiası cevap ve şiddetle başkalarına geçse de aynı tercih ederim. Bununla birlikte, tercih edilen yöntem işe yaramadığında yapmam gereken şey şu: (verilerin çapraz serileştirilmesiyle ilgili uzun hikaye). Bunu ve benzer ifadelerle bir switchifadeye bile zincirleyebilirsiniz case errInt == nil.

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

Yukarıda söylediğim gibi, bu şekilde denemeden önce ilk olarak tip iddiasını deneyin .


Belirtildiği gibi, JSON ayrıştırılırsa, değer float olacaktır. Bu durumda strconv.ParseFloat(v.(string), 64)yerine kullanın. Diyelim ki değişken isimlerini değiştirmek isteyebilirsiniz errFloat.
openwonk

0

Tür dönüşümünü daha iyi anlamak için aşağıdaki koda bakın:

package main
import "fmt"
func foo(a interface{}) {
    fmt.Println(a.(int))  // conversion of interface into int
}
func main() {
    var a int = 10
    foo(a)
}

Bu kod mükemmel çalışır ve arayüz tipini int tipine dönüştürür

Arabirim türündeki bir x ifadesi ve bir T türü için, birincil ifade x. (T), x'in sıfır olmadığını ve x'te depolanan değerin T türünde olduğunu iddia eder. X. (T) gösterimi bir tür iddiası olarak adlandırılır . Daha kesin olarak, eğer T bir arayüz tipi değilse, x. (T), x'in dinamik tipinin T tipiyle aynı olduğunu ileri sürer. Bu durumda, T, x'in (arayüz) tipini uygulamalıdır; aksi takdirde, x'in T tipi bir değeri saklaması mümkün olmadığından, tür iddiası geçersizdir. T bir arayüz tipiyse, x. (T), x'in dinamik türünün T arayüzünü uyguladığını iddia eder.

Kodunuza geri dönersek, bu

iAreaId := val.(int)

iyi çalışmalı. Dönüştürme sırasında oluşan hatayı kontrol etmek isterseniz yukarıdaki satıra aşağıdaki gibi yeniden yazabilirsiniz:

iAreaId, ok := val.(int)


0

Tür dönüştürmelerine yardımcı olabilecek bir kitaplık yazdım 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

Bunu yapmamın en basit yolu. En iyi yol değil, bildiğim en basit yol.

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

Arayüzünüzü {} int değerine dönüştürmek için tür iddiası yapmanız gerekir.

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

Daha fazla bilgi mevcuttur .


0

belki ihtiyacın var

func TransToString(data interface{}) (res string) {
    switch v := data.(type) {
    case float64:
        res = strconv.FormatFloat(data.(float64), 'f', 6, 64)
    case float32:
        res = strconv.FormatFloat(float64(data.(float32)), 'f', 6, 32)
    case int:
        res = strconv.FormatInt(int64(data.(int)), 10)
    case int64:
        res = strconv.FormatInt(data.(int64), 10)
    case uint:
        res = strconv.FormatUint(uint64(data.(uint)), 10)
    case uint64:
        res = strconv.FormatUint(data.(uint64), 10)
    case uint32:
        res = strconv.FormatUint(uint64(data.(uint32)), 10)
    case json.Number:
        res = data.(json.Number).String()
    case string:
        res = data.(string)
    case []byte:
        res = string(v)
    default:
        res = ""
    }
    return
}

-2

En iyisi, f'nin JSON'a karşılık gelen doğru tür olduğunu bildirerek çevrimden kaçının.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.