英文:
interface conversion: interface {} is float64 not []interface {} PubNub
问题
我正在尝试获取通过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", "channel1"]
这会引发以下错误:
panic: interface conversion: interface {} is float64, not []interface {} [recovered]
panic: interface conversion: interface {} is float64, not []interface {}
goroutine 1 [running]:
encoding/json.(*decodeState).unmarshal.func1(0xc042065c20)
C:/Go/src/encoding/json/decode.go:170 +0xf1
panic(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
encoding/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
请指导我正确的方向...
英文:
I am trying to get at the JSON values that are passed as a PubNub message on the subscribe end. the code for this is
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")
}
}
}
The format of the message is this
> [[{"Repo":"images","Server":"production"}], "149514560987662985",
> "channel1"]
This throws the following panic
> panic: interface conversion: interface {} is float64, not []interface
> {} [recovered]
> panic: interface conversion: interface {} is float64, not []interface {}
>
> goroutine 1 [running]:
> encoding/json.(*decodeState).unmarshal.func1(0xc042065c20)
> C:/Go/src/encoding/json/decode.go:170 +0xf1 panic(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 encoding/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
I was referencing the answer to this question
[https://stackoverflow.com/questions/29348262/decoding-pubnub-messages-with-golang-json][1]
Please point me in the right direction...?
[1]: https://stackoverflow.com/questions/29348262/decoding-pubnub-messages-with-golang-json "Decoding PubNub messages with golang JSON"
答案1
得分: 6
将传入的数据转换为[]interface{}
时,这将是一个漫长的过程,以恢复到原始的数据类型。以下是工作代码:
package main
import (
"encoding/json"
"fmt"
)
type DeployMessage struct {
Server string
Repo string
}
type PNMessage struct {
Messages []DeployMessage
Id string
Channel string
}
// 测试将此JSON编组
func main() {
// 假设我们在这里接收到数据。
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)
}
上述代码可以工作,但我不喜欢它。你可以像这样缩短代码并断言你的数据:
getData2 := getData[0].([]interface{})[0].(map[string]interface{})
repo := getData2["Repo"].(string) // 这将获取Repo的字符串值。
最终输出:
result = {Messages:[{Server:production Repo:images}] Id:149514560987662985 Channel:channel1}
链接:https://play.golang.org/p/U6slzSgaxu
英文:
When converting incoming data to []interface{}
, this is going to be long journey to get to the original data type. Here is the working code :
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)
}
Above code will works but I don't like it. https://play.golang.org/p/U6slzSgaxu
You can shorten the code the assert your data like this :
getData2 := getData[0].([]interface{})[0].(map[string]interface{})
repo := getData2["Repo"].(string) // this will get the value of Repo in string.
final output :
result = {Messages:[{Server:production Repo:images}] Id:149514560987662985 Channel:channel1}
答案2
得分: 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)
英文:
According to the panic message you pasted, error seems to be occurring in:
C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:43
Which seems to correspond to this line:
messages := arr[0].([]interface{})
You seem to be expecting that position to the array to hold another array, but apparently you are getting a float64 there, and thus the error:
interface conversion: interface {} is float64, not []interface {}
You can add some debugging to print out what you are getting in arr
at that point, so that you can then assert the type accordingly by adding this before that line 43:
fmt.Printf("arr: %#v\n", arr)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论