Получение интерфейса в структуру - PullRequest
0 голосов
/ 07 мая 2018

Я немного новичок в golang и пытаюсь обработать некоторые данные веб-сокета.

Я получаю данные в виде:

type Event struct {
    Event string      `json:"event"`
    Data  interface{} `json:"data"`
}

А поле Data - это объект json, который я хочу обработать и попасть в следующую структуру:

type OrderBook struct {
    Pair      string          `json:"pair"`
    Timestamp string          `json:"timestamp"`
    Broker    string          `json:"broker"`
    Bids      []OrderBookItem `json:"bids"`
    Asks      []OrderBookItem `json:"asks"`
}

type OrderBookItem struct {
    Price  float64
    Amount float64
}

из функции websocket:

....
case "data":
    publish(e.Data) <--- this is where the error occurs
....

который звонит:

func publish(data OrderBookResult) {
    log.Println("Publishing trade data...", data)

    o := &OrderBook{}
    o.Pair = "BTCEUR"
    o.Timestamp = data.Timestamp
    o.Broker = "Bitstamp"
    o.Asks = data.Asks
    o.Bids = data.Bids

}

Ошибка в функции websocket, которую я получаю, заключается в следующем:

cannot use e.Data (type interface {}) as type OrderBookResult in argument to publish: need type assertion

Как я могу "привести" структуру веб-сокета в новые поля структуры и ссылок, которые не определены в структуре веб-сокета. У меня есть node.js фон, и я еще не сообразился со строгостью го.

Thx

1 Ответ

0 голосов
/ 07 мая 2018

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

Но если ваш интерфейс получен из анализа JSON, он, скорее всего, будет содержать map[string]interface{}, а не OrderBookResult. См. здесь , почему это так.

Чтобы решить эту проблему, пожалуйста, прочитайте о том, как создать собственный маршаллер JSON. Например, в этом блоге. Ниже я также включил способ обработки map[string]interface{} для получения ваших данных в функции публикации.

Таким образом, вы можете ввести assert перед вызовом:

....
case "data":

    // Assert that e.Data is in fact a struct of type OrderBookResult
    if dataAsOrderBookResult, ok := e.Data.(OrderBookResult); ok {
        publish(dataAsOrderBookResult)
    } else {
        // handle error etc
        ...
    }

....

Или измените подпись вашей функции публикации и введите assert параметр внутри:

func publish(data interface{}) {
    log.Println("Publishing trade data...", data)

    o := &OrderBook{}
    // Type switch
    switch v := data.(type) {
    case OrderBookResult:
        o.Pair = "BTCEUR"
        o.Timestamp = v.Timestamp
        o.Broker = "Bitstamp"
        o.Asks = v.Asks
        o.Bids = v.Bids
    case map[string]interface{}:
        o.Pair = "BTCEUR"
        o.Timestamp = v["Timestamp"].(string)
        o.Broker = "Bitstamp"
        // here again you need to type assert correctly and it may be a map again
        //o.Asks = v["Asks"].(OrderBookItem)
        //o.Bids = v["Bids"].(OrderBookItem)
    default:
        // error handling etc.
        ...
    } 
...    
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...