gob panics解码接口

时间:2017-04-10 13:44:29

标签: go encoding gob

我有一个带有未导出字段的结构,应该进行gob编码和解码。

说:

type A struct {
    s int
}
func (a *A) Inc() {
    a.s++
}

显然,在这种情况下,我需要实现gob.GobEncodergob.GobDecoder接口。并且如果我直接使用结构,一切正常

https://play.golang.org/p/dm3HwaI8eU

但是我还需要一个实现相同逻辑并且可序列化的接口:

type Incer interface {
    gob.GobEncoder
    gob.GobDecoder
    Inc()
}

完整代码:https://play.golang.org/p/Zig2mPrnrq

突然间恐慌起来:

panic: interface conversion: interface is nil, not gob.GobDecoder [recovered]
    panic: interface conversion: interface is nil, not gob.GobDecoder

但如果我评论gob接口,一切都会变好。

我错过了重要的事情吗?所描述的行为对我来说似乎很奇怪

2 个答案:

答案 0 :(得分:2)

问题在于Incer接口实现了一个特殊的接口,特别适用于encoding/gob包:gob.GobDecoder

如果您的Incer接口仅包含Inc()方法,它将起作用,因为gob解码器看到您正在解码为接口类型,并且它将使用传输类型来解码值和在运行时检查解码的值(其类型是否包含在流中并在流中传输)实现目标接口类型,在这种情况下它将:

type Incer interface {
    Inc()
}

所以解码成功。

如果Incer接口还嵌入了gob.GobEncodergob.GobDecoder接口,则它们由 - 定义 - 负责进行编码/解码。如果类型实现这些接口,解码器将不会尝试使用传输的类型对值进行解码,而是调用目标值的GobDecode()方法,如果需要则创建零值。

由于您将nil值传递给Decoder.Decode(),解码器需要创建一个零值,但它不知道要实例化的类型,因为您传递的值是指向接口。您不能创建接口类型的值,只能创建可满足某些接口的具体类型的值。

您无法在gob.GobEncoder界面中加入gob.GobDecoderIncer。我知道你想确保实现确实实现它们,但是你可以看到 - 你将无法将它们解码为“通用”Incer接口值。另外,我甚至不认为有必要将它们包含在Incer中:gob.GobEncodergob.GobDecoder并不是使它们可传输的唯一方法,还有encoding.BinaryMarshaler和{由encoding/gob包检查的{3}}。

答案 1 :(得分:1)

在您的情况下,您需要定义什么是"布局"您希望解码转储到您的接口值的内存。当你宣布

var v Incer

您并未向解码器提供有关如何进行解码的任何线索。如果你对解码器说你期望解码一个main.A结构,它可以使用方法(* A).GobEncode()(* A).GobDecode ()你定义了:

var v Incer
v = &A{}

游乐场链接:https://play.golang.org/p/WUNRKGTVIS

这是example

中提供的gob documentation