接口转换:接口{} 是 float64 类型,而不是 []interface{} 类型的 PubNub。

huangapple go评论149阅读模式
英文:

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 (
&quot;encoding/json&quot;
&quot;flag&quot;
&quot;fmt&quot;
&quot;github.com/pubnub/go/messaging&quot;
)
type DeployMessages struct {
Server string
Repo   string
}
type PNMessage struct {
Messages []DeployMessages
Id       string
Channel  string
}
func main() {
publishKey := flag.String(&quot;pub&quot;, &quot;demo&quot;, &quot;publish key&quot;)
subscribeKey := flag.String(&quot;sub&quot;, &quot;demo&quot;, &quot;subscribe key&quot;)
channels := flag.String(&quot;channels&quot;, &quot;channel1, channel2&quot;, &quot;channels to subscribe to&quot;)
pubnub := messaging.NewPubnub(*publishKey, *subscribeKey, &quot;&quot;, &quot;&quot;, false, &quot;&quot;, nil)
successChannel := make(chan []byte)
errorChannel := make(chan []byte)
go pubnub.Subscribe(*channels, &quot;&quot;, successChannel, false, errorChannel)
subscribeHandler(successChannel, errorChannel, &quot;Subscribe&quot;)
}
func (pnm *PNMessage) UnmarshalJSON(bs []byte) error {
var arr []interface{}
err := json.Unmarshal(bs, &amp;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{})[&quot;server&quot;].(string) 
pnm.Messages[i].Repo = m.(map[string]interface{})[&quot;repo&quot;].(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 := &lt;-successChannel:
if !ok {
break
}
if string(response) != &quot;[]&quot; {
message := PNMessage{}
err := json.Unmarshal([]byte(response), &amp;message)
if err != nil {
break
}
fmt.Println(fmt.Sprintf(&quot;%s Response: %s &quot;, action, response))
fmt.Println(&quot;&quot;)
}
case failure, ok := &lt;-errorChannel:
if !ok {
break
}
if string(failure) != &quot;[]&quot; {
if true {
fmt.Printf(&quot;%s Error Response: %s &quot;, action, failure)
fmt.Println(&quot;&quot;)
}
}
case &lt;-messaging.SubscribeTimeout():
fmt.Printf(&quot;Subscirbe request timeout&quot;)
}
}
}

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 (
&quot;encoding/json&quot;
&quot;fmt&quot;
)
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(`[[{&quot;Repo&quot;:&quot;images&quot;,&quot;Server&quot;:&quot;production&quot;}], &quot;149514560987662985&quot;, &quot;channel1&quot;]`)
var getData []interface{}
err := json.Unmarshal(data, &amp;getData)
if err != nil {
panic(err)
}
fmt.Printf(&quot;result  getData = %+v\n&quot;, getData[0])
getData2 := getData[0].([]interface{})
fmt.Printf(&quot;result  getData = %+v\n&quot;, getData2[0])
getData3 := getData2[0].(map[string]interface{})
var deployMessages []DeployMessage
deployMessages = append(deployMessages, DeployMessage{Server: getData3[&quot;Server&quot;].(string), Repo: getData3[&quot;Repo&quot;].(string)})
pNMessage := PNMessage{
Messages: deployMessages,
Id:       getData[1].(string),
Channel:  getData[2].(string),
}
fmt.Printf(&quot;result  = %+v\n&quot;, 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[&quot;Repo&quot;].(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(&quot;arr: %#v\n&quot;, arr)

huangapple
  • 本文由 发表于 2017年5月19日 06:17:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/44058631.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定