Golang данные как интерфейс {} паники - PullRequest
0 голосов
/ 08 апреля 2020

Суслики,

Я пытаюсь реализовать пакет отражения Go и действительно застрял в одном.

context - я пытаюсь вызвать API, который возвращает - time.Time и некоторые данные в интерфейсе {}. Эти данные могут быть большей частью int / int64 или float32 / float64. Я беру данные в интерфейсе {} и далее создаю структуру, в которой я сохраняю данные интерфейса {} в интерфейсе, что отражает многообещающие вещи, которые я мог бы сделать с интерфейсом

type dataStore struct {
   CreateTime time.Time
   Data interface{}
}

Затем я создаю map[string][]dataStore для хранения данных из API, который я получаю.

Я пытаюсь сделать следующее, чтобы получить значения Float64, которые, как я знаю, поступают, и я хочу сделать с ними некоторые математические вычисления:

x := map[string][]dataStore {}
ReadDatafromAPI(x) // I call the API to read the data into variable x

//Assume map["CA"][]dataStore{{2020-03-31 21:55:52.123456, 123.4567890123e10},}

fmt.Println(x["CA"][0].Data) // This prints the data 123.4567890123e10, no problem

fmt.Println(reflect.ValueOf(x["CA"][0].Data))// this prints reflect.Value

va := reflect.ValueOf(x["CA"][0].Data) 

fmt.Println(va.(float64)) // panic: interface conversion: interface {} is reflect.Value, not float64

fmt.Println(va.Interface()) // prints 123.4567890123e10
fmt.Println(va.Kind()) // prints struct
fmt.Println(va.NumField()) // prints 2 and I can fetch the fields using Field(0) and Field(1) -- the data doesn't make sense to me. not sure if those are pointers or what

У меня есть только одна цель - получить float64 как float64 и int как int. Значение означает отражение того, как оно должно быть использовано.

Любое понимание будет высоко оценено.

Заранее спасибо.


Люди - спасибо за все ответы и указатели. Я ценю это! Похоже, я все еще получаю отражать. Значение как тип, а не float64 / 32, как ожидалось. Смотрите ниже:

switch flt := x["CA"][0].Data.(type) {
case float64:
        fmt.Println("Data is float64 -> ", flt)
    fmt.Printf("Type for flt is %T -> ", flt)
case float32:
        fmt.Println("Data is float32 -> ", flt)
    fmt.Printf("Type for flt is %T -> ", flt)
default:
    fmt.Println("Its default!")
    fmt.Printf("Type for flt is %T -> ", flt) // I always get here with reflect.Value as the Type. Never a float64 which is the value store without any question
}


if nflt, ok := x["CA"][0].Data.(float64); ok {
    fmt.Println("nflt is float64")
} else {
    fmt.Println("nflt is not float64) // I always get to Else
}

Ответы [ 2 ]

3 голосов
/ 08 апреля 2020

Вам не нужно отражение, чтобы преобразовать интерфейс в один из известных типов. Вам нужны утверждения типа или переключатель типа:

if flt, ok:=data.(float64); ok {
   // flt is float64
}
if i, ok:=data.(int); ok {
   // i is int
}

Или:

switch k:=data.(type) {
  case float64:
     // Here, k is float64
  case int:
     // Here, k is int
}
2 голосов
/ 08 апреля 2020

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

  d, ok := (x["CA"][0].Data.(float64)
  if ok {
     // it's a float64, do something with d.
  }

или используйте переключатель типа :

 switch d := x["CA"][0].Data.(type) {
 case int:
     // d is an int
 case float64:
     // d is a float64
 ... and other types as needed
 default:
     // handle unexpected type
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...