将 interface {}转换为 int

我试图从一个 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
225398 次浏览

而不是

iAreaId := int(val)

你想要 类型断言类型断言:

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

不能使用 改变信仰接口类型化值的原因是引用的 specs 部分中的这些规则:

转换是形式 T(x)的表达式,其中 T是一个类型,而 x是一个可以转换为 T 类型的表达式。

...

在以下任何情况下,非常数值 x 都可以转换为 T 类型:

  1. X 可以赋给 T。
  2. X 的类型和 T 有相同的基础类型。
  3. X 的类型和 T 是未命名的指针类型,它们的指针基类型具有相同的底层类型。
  4. X 的类型和 T 都是整数类型或浮点类型。
  5. X 的类型和 T 都是复杂类型。
  6. X 是一个整数或一片字节或符号,T 是一个字符串类型。
  7. X 是一个字符串,T 是一片字节或符号。

但是

iAreaId := int(val)

没有任何一种情况1.7。

我假设: 如果您通过浏览器发送 JSON 值,那么您发送的任何数字都将是 float64类型,因此您不能直接在 golang 中获取值 int。

所以转换是这样的:

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


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

这样你就可以得到你想要的确切价值。

我完全同意 滋滋类型断言类型断言答案,我强烈地喜欢这种方式超过其他人。也就是说,当首选方法不起作用时,我必须这样做... ... (与交叉序列化数据有关的故事很长)。您甚至可以使用 case errInt == nil和类似的表达式将其链接成 switch语句。

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

正如我上面所说的,在尝试这种方法之前先尝试 类型断言类型断言

为了更好地理解类型转换,请查看下面的代码:

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,主表达式 (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)

最好通过将 f 声明为与 JSON 对应的正确类型 f 来避免强制转换。

要将接口{}转换为 int 值,需要执行类型断言。

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

更多信息是 有空

我编写了一个可以帮助进行类型转换的库 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]

我做这件事的最简单的方法,不是最好的方法,而是我知道的最简单的方法。

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
}

添加另一个答案,使用 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)
}

也许你需要

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
}

您可以使用 反思来帮助您确定类型,然后进行转换。

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