我正在尝试从JSON获取值并将其转换为int但它不起作用,我不知道如何正确地执行它。
以下是错误消息:
...cannot convert val (type interface {}) to type int: need type assertion
代码:
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
答案 0 :(得分:150)
而不是
iAreaId := int(val)
你想要一个type assertion:
iAreaId := val.(int)
iAreaId, ok := val.(int) // Alt. non panicking version
您不能convert接口类型值的原因是参考规范部分中的这些规则:
转化是
T(x)
形式的表达式,其中T
是一种类型,x
是一个可以转换为T类型的表达式。
...
在任何这些情况下,非常数值x都可以转换为类型T:
- x可分配给T。
- x的类型和T具有相同的基础类型。
- x的类型和T是未命名的指针类型,它们的指针基类型具有相同的基础类型。
- x的类型和T都是整数或浮点类型。
- x的类型和T都是复杂类型。
- x是一个整数或一个字节或符文切片,T是一个字符串类型。
- x是一个字符串,T是一个字节或符文的片段。
醇>
但是
iAreaId := int(val)
不任何案例1.-7。
答案 1 :(得分:21)
我假设:如果您通过浏览器发送了JSON值,那么您发送的任何数字都将是float64类型,因此您无法直接在golang中获取值。
转换如此:
//As that says:
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64
var iAreaId int = int(val.(float64))
通过这种方式,您可以获得所需的精确值。
答案 2 :(得分:3)
我全心全意地同意zzzz的类型断言回答,我更喜欢这种方式。也就是说,这是我在首选方法无法工作时必须做的事情......(与数据交叉序列化有关的长篇故事)。您甚至可以将其链接到switch
语句,其中包含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 */
}
}
就像我上面说过的那样,在尝试这种方式之前先尝试键入断言。
答案 3 :(得分:1)
添加另一个使用switch
的答案...那里有更全面的示例,但这将为您提供思路。
例如,t
成为每个case
范围内的指定数据类型。请注意,您只需要为一种类型的类型提供case
,否则t
仍然是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)
}
答案 4 :(得分:0)
答案 5 :(得分:0)
我写了一个可以帮助进行类型转换的库 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]
答案 6 :(得分:0)
我这样做的最简单方法。不是最好的方法,而是我知道的最简单的方法。
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
}
答案 7 :(得分:0)
也许您需要
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
}
答案 8 :(得分:0)
您可以使用 reflect 来帮助您确定类型,然后进行转换。
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")
}
}
答案 9 :(得分:-1)
要更好地理解类型转换,请查看以下代码:
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)
}
此代码执行完美,并将接口类型转换为int类型
对于接口类型的表达式x和类型T,主表达式 x。(T)断言x不是nil并且存储在x中的值是T类型。符号x。(T)称为类型断言。 更确切地说,如果T不是接口类型,则x。(T)断言x的动态类型与类型T相同。在这种情况下,T必须实现x的(接口)类型;否则类型断言无效,因为x不可能存储类型T的值。如果T是接口类型,则x。(T)断言x的动态类型实现接口T.
回到你的代码,这个
iAreaId := val.(int)
应该运作良好。如果要检查转换时发生的错误,还可以将上面的行重写为
iAreaId, ok := val.(int)
答案 10 :(得分:-1)
最好通过将f声明为与JSON对应的正确类型来避免强制转换。