将interface {}转换为int

时间:2013-08-04 09:00:20

标签: go

我正在尝试从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

11 个答案:

答案 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:

     
      
  1. x可分配给T。
  2.   
  3. x的类型和T具有相同的基础类型。
  4.   
  5. x的类型和T是未命名的指针类型,它们的指针基类型具有相同的基础类型。
  6.   
  7. x的类型和T都是整数或浮点类型。
  8.   
  9. x的类型和T都是复杂类型。
  10.   
  11. x是一个整数或一个字节或符文切片,T是一个字符串类型。
  12.   
  13. x是一个字符串,T是一个字节或符文的片段。
  14.   

但是

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)

您需要键入断言以将接口{}转换为int值。

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

更多信息是available

答案 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")
    }
}

Go Playground

答案 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对应的正确类型来避免强制转换。