【问题标题】:interface conversion: interface {} is float64 not []interface {} PubNub接口转换:interface {} 是 float64 而不是 []interface {} PubNub
【发布时间】:2017-05-18 22:17:47
【问题描述】:

我试图获取在订阅端作为 PubNub 消息传递的 JSON 值。代码是

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "github.com/pubnub/go/messaging"
)

type DeployMessages struct {
    Server string
    Repo   string
}

type PNMessage struct {
    Messages []DeployMessages
    Id       string
    Channel  string
}

func main() {
    publishKey := flag.String("pub", "demo", "publish key")
    subscribeKey := flag.String("sub", "demo", "subscribe key")

    channels := flag.String("channels", "channel1, channel2", "channels to subscribe to")

    pubnub := messaging.NewPubnub(*publishKey, *subscribeKey, "", "", false, "", nil)

    successChannel := make(chan []byte)
    errorChannel := make(chan []byte)

    go pubnub.Subscribe(*channels, "", successChannel, false, errorChannel)

    subscribeHandler(successChannel, errorChannel, "Subscribe")
}

func (pnm *PNMessage) UnmarshalJSON(bs []byte) error {
    var arr []interface{}
    err := json.Unmarshal(bs, &arr)
    if err != nil {
        return err
    }
    messages := arr[0].([]interface{}) 
    pnm.Messages = make([]DeployMessages, len(messages))
    for i, m := range messages {
        pnm.Messages[i].Server = m.(map[string]interface{})["server"].(string) 
        pnm.Messages[i].Repo = m.(map[string]interface{})["repo"].(string)
    }
    pnm.Id = arr[1].(string)      
    pnm.Channel = arr[2].(string)
    return nil
}

func subscribeHandler(successChannel, errorChannel chan []byte, action string) {

    for {
        select {
        case response, ok := <-successChannel:
            if !ok {
                break
            }
            if string(response) != "[]" {
                message := PNMessage{}
                err := json.Unmarshal([]byte(response), &message)
                if err != nil {
                    break
                }
                fmt.Println(fmt.Sprintf("%s Response: %s ", action, response))
                fmt.Println("")
            }

        case failure, ok := <-errorChannel:
            if !ok {
                break
            }
            if string(failure) != "[]" {
                if true {
                    fmt.Printf("%s Error Response: %s ", action, failure)
                    fmt.Println("")
                }
            }

        case <-messaging.SubscribeTimeout():
            fmt.Printf("Subscirbe request timeout")
        }
    }
}

消息的格式是这样的

[[{"Repo":"images","Server":"production"}], "149514560987662985", “频道1”]

这会引发以下恐慌

panic:接口转换:interface {} 是 float64,而不是 []interface {} [恢复] 恐慌:接口转换:接口{}是float64,而不是[]接口{}

goroutine 1 [运行中]: 编码/json.(*decodeState).unmarshal.func1(0xc042065c20) C:/Go/src/encoding/json/decode.go:170 +0xf1 恐慌(0x6548e0, 0xc042009440) C:/Go/src/runtime/panic.go:489 +0x2dd main.(*PNMessage).UnmarshalJSON(0xc0420093c0, 0xc042009300, 0x3d, 0x40, 0x0, 0xb35198) C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:43 +0x499 编码/json.(*decodeState).array(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x16) C:/Go/src/encoding/json/decode.go:489 +0xbe4 encoding/json.(*decodeState).value(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x16) C:/Go/src/encoding/json/decode.go:399 +0x28e encoding/json.(*decodeState).unmarshal(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x0, 0x0) C:/Go/src/encoding/json/decode.go:184 +0x221 encoding/json.Unmarshal(0xc042009300, 0x3d, 0x40, 0x64e6a0, 0xc0420093c0, 0xc042065c98, 0x5f82de) C:/Go/src/encoding/json/decode.go:104 +0x14f main.subscribeHandler(0xc042030c00, 0xc042030c60, 0x69c4a4, 0x9) C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:64 +0x222 main.main() C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:34 +0x27e

我在参考这个问题的答案 https://stackoverflow.com/questions/29348262/decoding-pubnub-messages-with-golang-json 请指出正确的方向...?

【问题讨论】:

    标签: go pubnub subscribe


    【解决方案1】:

    将传入数据转换为[]interface{} 时,要获得原始数据类型将是一个漫长的旅程。这是工作代码:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type DeployMessage struct {
        Server string
        Repo   string
    }
    
    type PNMessage struct {
        Messages []DeployMessage
        Id       string
        Channel  string
    }
    
    // testing to marshal this json
    func main() {
        // imagine if we have receive our data here.
        data := []byte(`[[{"Repo":"images","Server":"production"}], "149514560987662985", "channel1"]`)
    
        var getData []interface{}
        err := json.Unmarshal(data, &getData)
        if err != nil {
            panic(err)
        }
        fmt.Printf("result  getData = %+v\n", getData[0])
    
        getData2 := getData[0].([]interface{})
        fmt.Printf("result  getData = %+v\n", getData2[0])
    
        getData3 := getData2[0].(map[string]interface{})
    
        var deployMessages []DeployMessage
        deployMessages = append(deployMessages, DeployMessage{Server: getData3["Server"].(string), Repo: getData3["Repo"].(string)})
    
        pNMessage := PNMessage{
            Messages: deployMessages,
            Id:       getData[1].(string),
            Channel:  getData[2].(string),
        }
    
        fmt.Printf("result  = %+v\n", pNMessage)
    
    }
    

    上面的代码可以工作,但我不喜欢它。 https://play.golang.org/p/U6slzSgaxu

    您可以像这样缩短断言数据的代码:

    getData2 := getData[0].([]interface{})[0].(map[string]interface{})
    repo := getData2["Repo"].(string) // this will get the value of Repo in string.
    

    最终输出:

    result  = {Messages:[{Server:production Repo:images}] Id:149514560987662985 Channel:channel1}
    

    【讨论】:

      【解决方案2】:

      根据您粘贴的恐慌消息,错误似乎发生在:

      C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:43
      

      这似乎对应于这一行:

      messages := arr[0].([]interface{})
      

      您似乎期望该数组的位置可以容纳另一个数组,但显然您在那里得到了一个 float64,因此出现了错误:

      interface conversion: interface {} is float64, not []interface {}
      

      您可以添加一些调试以打印出您当时在 arr 中获得的内容,以便您可以通过在第 43 行之前添加相应的断言来相应地声明类型:

      fmt.Printf("arr: %#v\n", arr)
      

      【讨论】:

      • 它是空输出:arr:[]
      • 这很奇怪。如果这是一个空数组,那么下一行应该抛出一个“索引超出范围”错误而不是 float64 错误。即使打印空数组,您是否始终收到 float64 错误?您帖子中的行号是否与您原始程序中的行号一致?
      猜你喜欢
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 2015-01-14
      • 2018-08-10
      相关资源
      最近更新 更多