interface {}를 int로 변환


100

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

답변:


201

대신에

iAreaId := int(val)

유형 어설 션 을 원합니다 .

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

인터페이스 유형 값을 변환 할 수없는 이유 는 참조 된 스펙 파트의 다음 규칙 때문입니다.

전환은 형태의 표현식 타입이고 T. 유형으로 변환 될 수있는 표현이며T(x)Tx

...

다음과 같은 경우 상수가 아닌 값 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의 경우 가 아닙니다 .


좋은 대답입니다! 언어 사양은 항상 답을 찾기에 가장 좋은 곳입니다!
Hot.PxL 2014

감사. 아름다운 대답입니다.
Muktadir

30

나는 가정하고있다 : 브라우저를 통해 JSON 값을 보낸 경우 보낸 숫자는 float64 유형이므로 golang에서 직접 값을 가져올 수 없습니다.

따라서 다음과 같이 변환하십시오.

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

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

이렇게하면 원하는 정확한 가치를 얻을 수 있습니다.


@Mujibur가 100 % 맞습니다.하지만 JSON 사양에는 정수 유형이 있기 때문에 어떤 이유에서든
kamal

@kamal은 JSON이 자바 스크립트 구문과 정의를 사용하기 때문입니다. JavaScript는 64 비트 부동 소수점 숫자 만 지원합니다. Ref # javascript.info/number
Mujibur

4

사용하는 또 다른 답변 추가 switch... 더 포괄적 인 예가 있지만 아이디어를 얻을 수 있습니다.

예를 들어, tcase범위 내에서 지정된 데이터 유형이됩니다 . 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)
}

의 경우 case string사용 strconv.ParseFloat(t, 32)하여 결과를 다음으로 캐스팅 할 수 있습니다 .int
JVE999

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

위에서 말했듯 이 이런 식으로 시도하기 전에 먼저 유형 어설 션 을 시도하십시오.


지적했듯이 JSON을 구문 분석하면 값은 부동 소수점입니다. 이 경우 strconv.ParseFloat(v.(string), 64)대신 사용하십시오. 변수 이름도 변경할 수 있습니다 errFloat.
openwonk

0

유형 변환을 더 잘 이해하려면 아래 코드를보십시오.

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)


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]

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
}


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
}

-2

f를 JSON에 해당하는 올바른 유형으로 선언하여 캐스팅을 피하는 것이 가장 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.