Преобразовать интерфейс {} в 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
любая помощь будет оценена.
Ответы
Ответ 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)