Подтвердить что ты не робот

Преобразовать интерфейс {} в int в Голанге

Я новичок в Golang, и я пытаюсь получить значение от 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

любая помощь будет оценена.

4b9b3361

Ответ 1

Вместо

iAreaId := int(val)

вы хотите утверждение типа:

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

Причина, по которой вы не можете конвертировать значение, указанное в интерфейсе, - это эти правила в разделе специфицированных спецификаций:

Конверсии - это выражения формы T(x), где T - тип, а x - это выражение, которое может быть преобразовано в тип T.

...

Непостоянное значение x может быть преобразовано в тип T в любом из этих случаев:

  • x присваивается T.
  • x type и T имеют одинаковые базовые типы.
  • x type и T - неназванные типы указателей, а их базовые типы указателей имеют одинаковые базовые типы.
  • x type и T являются целыми или с плавающей точкой.
  • x type и T являются сложными типами.
  • x - целое число или фрагмент байтов или рун, а T - строковый тип.
  • x - строка, а T - фрагмент байтов или рун.

Но

iAreaId := int(val)

не является случаем 1.-7.

Ответ 2

Я предполагаю: если вы отправили значение JSON через браузер, то любое число, которое вы отправили, будет типом float64, поэтому вы не можете получить значение непосредственно int в golang.

Итак, сделайте преобразование следующим образом:

//Как сказано: fmt.Fprintf(w, "Тип =% v", val)//< --- Тип = float64

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

Таким образом, вы можете получить точное значение, что вы хотели.

Ответ 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 */
    }
}

Как я уже говорил выше, сначала попробуйте утверждение типа, прежде чем пытаться это сделать.

Ответ 4

Чтобы лучше понять преобразование типов, посмотрите на код ниже:

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; в противном случае утверждение типа является недопустимым, поскольку х не может хранить значение типа Т. Если T является типом интерфейса, x. (T) утверждает, что динамический тип x реализует интерфейс T.

Возвращаясь к вашему коду,

iAreaId := val.(int)

должен работать хорошо. Если вы хотите проверить, что ошибка произошла во время преобразования, вы также можете переписать выше строку как

iAreaId, ok := val.(int)