Próbuję uzyskać wartość z JSON i rzutować ją na int, ale to nie działa i nie wiem, jak to zrobić poprawnie.
Oto komunikat o błędzie:
...cannot convert val (type interface {}) to type int: need type assertion
A 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
Zakładam: jeśli wysłałeś wartość JSON przez przeglądarkę, to każda wysłana liczba będzie typu float64, więc nie możesz uzyskać wartości bezpośrednio w golang.
Zrób więc konwersję jak:
//As that says: fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64 var iAreaId int = int(val.(float64))
W ten sposób możesz uzyskać dokładną wartość, jaką chciałeś.
źródło
Dodanie kolejnej odpowiedzi, która używa
switch
... Istnieją bardziej wyczerpujące przykłady, ale to da ci pomysł.Na przykład
t
staje się określonym typem danych w każdymcase
zakresie. Uwaga, musisz podaćcase
tylko jeden typ w typie, w przeciwnym raziet
pozostajeinterface
.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) }
źródło
case string
, można użyćstrconv.ParseFloat(t, 32)
, a następnie rzucić wynik doint
I całym sercem zgadzam się z zzzz „s typu twierdzenie odpowiedź, a ja zdecydowanie wolę ten sposób nad innymi. To powiedziawszy, oto, co musiałem zrobić, gdy preferowana metoda nie zadziałała ... (długa historia związana z cross-serializacją danych). Możesz nawet połączyć to w
switch
instrukcję zcase errInt == nil
i podobnymi wyrażeniami.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 */ } }
Jak powiedziałem powyżej, spróbuj najpierw potwierdzić typ, zanim spróbujesz w ten sposób.
źródło
strconv.ParseFloat(v.(string), 64)
zamiast tego. Na przykład możesz chcieć zmienić nazwy zmiennycherrFloat
.Aby lepiej zrozumieć konwersję typów, spójrz na poniższy kod:
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) }
Ten kod działa doskonale i konwertuje typ interfejsu na typ int
Wracając do twojego kodu, to
iAreaId := val.(int)
powinno działać dobrze. Jeśli chcesz sprawdzić, czy wystąpił błąd podczas konwersji, możesz również ponownie napisać powyższą linię jako
iAreaId, ok := val.(int)
źródło
Napisałem bibliotekę, która może pomóc w konwersji typów 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]
źródło
Najprościej to zrobiłem. Nie jest to najlepszy sposób, ale najprostszy sposób, jaki znam.
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 }
źródło
Musisz wykonać asercję typu, aby przekonwertować interfejs {} na wartość int.
iAreaId := val.(int) iAreaId, ok := val.(int)
Więcej informacji jest dostępnych .
źródło
może potrzebujesz
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 }
źródło
Najlepiej unikać rzutowania, deklarując f jako poprawny typ, odpowiadający JSON.
źródło