[go] 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



답변

대신에

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의 경우 가 아닙니다 .


답변

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

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

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

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

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


답변

사용하는 또 다른 답변 추가 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)
}


답변

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

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


답변

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

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)


답변

유형 변환에 도움이되는 라이브러리를 작성했습니다.
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
}