将interface{}转换为int类型。

huangapple go评论76阅读模式
英文:

Convert interface{} to int

问题

我正在尝试从JSON中获取一个值并将其转换为整数,但是它不起作用,我不知道如何正确地做。

以下是错误消息:

...无法将val(类型为interface {})转换为int:需要类型断言

这是代码:

var f interface{}
err = json.Unmarshal([]byte(jsonStr), &f)
if err != nil {
    utility.CreateErrorResponse(w, "错误:解析JSON数据失败。")
    return
}

m := f.(map[string]interface{})

val, ok := m["area_id"]
if !ok {
    utility.CreateErrorResponse(w, "错误:提交的数据中缺少区域ID。")
    return
}

fmt.Fprintf(w, "类型 = %v", val)   // <--- 类型 = float64
iAreaId := int(val)                // <--- 在这一行出错。
testName := "Area_" + iAreaId      // 没有执行到这里
英文:

I'm trying to get a value from a JSON and cast it to int but it doesn't work, and I don't know how to do it properly.

Here is the error message:

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

And the code:

	var f interface{}
	err = json.Unmarshal([]byte(jsonStr), &amp;f)
	if err != nil {
		utility.CreateErrorResponse(w, &quot;Error: failed to parse JSON data.&quot;)
		return
	}

	m := f.(map[string]interface{})

	val, ok := m[&quot;area_id&quot;]
	if !ok {
		utility.CreateErrorResponse(w, &quot;Error: Area ID is missing from submitted data.&quot;)
		return
	}

	fmt.Fprintf(w, &quot;Type = %v&quot;, val)   // &lt;--- Type = float64
	iAreaId := int(val)                // &lt;--- Error on this line.
	testName := &quot;Area_&quot; + iAreaId      // not reaching here

答案1

得分: 278

而不是

iAreaId := int(val)

你想要一个 类型断言

iAreaId := val.(int)
iAreaId, ok := val.(int) // 另一种非 panic 版本

你不能将一个接口类型的值 转换 的原因是在引用规范的这些部分中有这些规则:

> 转换是形式为 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. 中的任何一种情况。

英文:

Instead of

iAreaId := int(val)

you want a type assertion:

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

The reason why you cannot convert an interface typed value are these rules in the referenced specs parts:

> Conversions are expressions of the form T(x) where T is a type and x is an expression that can be converted to type T.

...

> A non-constant value x can be converted to type T in any of these cases:
>
> 1. x is assignable to T.
> 2. x's type and T have identical underlying types.
> 3. x's type and T are unnamed pointer types and their pointer base types have identical underlying types.
> 4. x's type and T are both integer or floating point types.
> 5. x's type and T are both complex types.
> 6. x is an integer or a slice of bytes or runes and T is a string type.
> 7. x is a string and T is a slice of bytes or runes.

But

iAreaId := int(val)

is not any of the cases 1.-7.

答案2

得分: 56

我假设:如果你通过浏览器发送了 JSON 值,那么你发送的任何数字都将被视为 float64 类型,因此在 golang 中无法直接获取 int 值。

所以进行如下转换:

//根据以下代码:
fmt.Fprintf(w, "Type = %v", val) // <--- Type = float64

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

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

英文:

I am assuming: If you sent the JSON value through browser then any number you sent that will be the type float64 so you cant get the value directly int in golang.

So do the conversion like:

//As that says: 
fmt.Fprintf(w, &quot;Type = %v&quot;, val) // &lt;--- Type = float64

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

This way you can get exact value what you wanted.

答案3

得分: 7

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

希望对你有帮助!

英文:

Adding another answer that uses switch... There are more comprehensive examples out there, but this will give you the idea.

In example, t becomes the specified data type within each case scope. Note, you have to provide a case for only one type at a type, otherwise t remains an interface.

package main
import &quot;fmt&quot;
func main() {
var val interface{} // your starting value
val = 4
var i int // your final value
switch t := val.(type) {
case int:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = t
case int8:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case int16:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case int32:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case int64:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case bool:
fmt.Printf(&quot;%t == %T\n&quot;, t, t)
// // not covertible unless...
// if t {
//	i = 1
// } else {
//	i = 0
// }
case float32:
fmt.Printf(&quot;%g == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case float64:
fmt.Printf(&quot;%f == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case uint8:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case uint16:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case uint32:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case uint64:
fmt.Printf(&quot;%d == %T\n&quot;, t, t)
i = int(t) // standardizes across systems
case string:
fmt.Printf(&quot;%s == %T\n&quot;, t, t)
// gets a little messy...
default:
// what is it then?
fmt.Printf(&quot;%v == %T\n&quot;, t, t)
}
fmt.Printf(&quot;i == %d\n&quot;, i)
}

答案4

得分: 5

我完全同意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 是一个整数", i)
        /* 在这里对 "i" 做你想做的事情 */
    }
}

就像我上面说的,在尝试这种方式之前,请先尝试类型断言。

英文:

I whole-heartedly agree with zzzz's type assertion answer and I strongly prefer that way over others. That said, here's what I've had to do when the preferred method has not worked... (long story related to cross-serialization of data). You can even chain this into a switch statement with case errInt == nil and similar expressions.

package main
import &quot;fmt&quot;
import &quot;strconv&quot;
func main() {
var v interface{}
v = &quot;4&quot;
i, errInt := strconv.ParseInt(v.(string), 10, 64)
if errInt == nil {
fmt.Printf(&quot;%d is a int&quot;, i)
/* do what you wish with &quot;i&quot; here */
}
}

Like I said above, try type assertion first before trying this way.

答案5

得分: 3

也许你需要这样的代码:

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
}
英文:

maybe you need

func TransToString(data interface{}) (res string) {
	switch v := data.(type) {
	case float64:
		res = strconv.FormatFloat(data.(float64), &#39;f&#39;, 6, 64)
	case float32:
		res = strconv.FormatFloat(float64(data.(float32)), &#39;f&#39;, 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 = &quot;&quot;
	}
	return
}

答案6

得分: 3

你可以使用reflect来帮助确定类型,然后进行转换。

func i2num(a interface{}) (interface{}, error) { // 将接口转换为数字
    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("类型错误")
    }
}

将interface{}转换为int类型。

英文:

You can use reflect to help you determine the type and then convert.

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(&quot;type error&quot;)
    }
}

将interface{}转换为int类型。

答案7

得分: 1

使用cast.ToInt(anyValue)

我需要这个,因为我需要使用的那个糟糕的端点有一个 bug,有时会将整数返回为字符串,有时会返回为 float64。

https://github.com/spf13/cast

英文:

use cast.ToInt(anyValue)

I needed that, because the nasty endpoint which I need to use has a bug and sometimes is returning an integer as a string, sometimes as float64

https://github.com/spf13/cast

答案8

得分: 0

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

package main
import "fmt"
func foo(a interface{}) {
    fmt.Println(a.(int))  // 将接口转换为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)
英文:

To better understand the type conversion, look at the code below:

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

This code executes perfectly and converts interface type to int type

> For an expression x of interface type and a type T, the primary expression
x.(T) asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.
More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T. In this case, T must implement the (interface) type of x; otherwise the type assertion is invalid since it is not possible for x to store a value of type T. If T is an interface type, x.(T) asserts that the dynamic type of x implements the interface T.

Going back to your code, this

iAreaId := val.(int)

should work good. If you want to check error occured while conversion, you can also re-write above line as

iAreaId, ok := val.(int)

答案9

得分: 0

你需要对接口{}进行类型断言,将其转换为int值。

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

更多信息请参考这里

英文:

You need to do type assertion for converting your interface{} to int value.

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

More information is available.

答案10

得分: 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]
英文:

I wrote a library that can help with type convertions
https://github.com/KromDaniel/jonson

js := jonson.New([]interface{}{55.6, 70.8, 10.4, 1, &quot;48&quot;, &quot;-90&quot;})
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() &gt; 50{
jsn.MutateToString()
}
return jsn
}) // [&quot;55&quot;,&quot;70&quot;,10,1,48,-90]

答案11

得分: 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
}

这段代码的功能是将两个数字相加并返回结果。在main函数中,调用了addTwoNumbers函数,并将参数设置为5和6。addTwoNumbers函数接受两个参数val1val2,这两个参数的类型是interface{},表示可以接受任意类型的参数。在函数内部,通过类型断言将val1val2转换为int类型,并将它们相加后返回结果。在main函数中,使用fmt.Print打印出函数的返回值。

英文:

Simplest way I did this. Not the best way but simplest way I know how.

import &quot;fmt&quot;
func main() {
fmt.Print(addTwoNumbers(5, 6))
}
func addTwoNumbers(val1 interface{}, val2 interface{}) int {
op1, _ := val1.(int)
op2, _ := val2.(int)
return op1 + op2
}

答案12

得分: -2

最好避免通过将 f 转换为正确类型来对应 JSON。

英文:

Best avoid casting by declaring f to be f the correct type to correspond to the JSON.

huangapple
  • 本文由 发表于 2013年8月4日 17:00:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/18041334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定