gob 恐慌解码接口

yal*_*gko 6 encoding go gob

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

说:

type A struct {
    s int
}
func (a *A) Inc() {
    a.s++
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

type Incer interface {
    gob.GobEncoder
    gob.GobDecoder
    Inc()
}
Run Code Online (Sandbox Code Playgroud)

完整代码: 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
Run Code Online (Sandbox Code Playgroud)

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

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

icz*_*cza 6

问题在于该Incer接口实现了一个特殊的接口,对于encoding/gob包来说是特殊的:gob.GobDecoder

\n\n

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

\n\n
type Incer interface {\n    Inc()\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样解码就成功了。

\n\n

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

\n\n

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

\n\n

您不能在界面中包含gob.GobEncoder和。我知道您想确保实现确实实现了它们,但是 \xe2\x80\x93 正如您所看到的 \xe2\x80\x93 您将无法将它们解码为“通用”接口值。另外,我什至不认为有必要将它们包含在:中,并且并不是使它们可传输的唯一方法,还有由包检查的和。gob.GobDecoderIncerIncerIncergob.GobEncodergob.GobDecoderencoding.BinaryMarshalerencoding.BinaryUnmarshalerencoding/gob

\n

  • 请注意,如果“encoding.BinaryUnmarshaler”接口是该接口的一部分,您将收到类似的恐慌(“恐慌:接口转换:接口为nil,而不是encoding.BinaryUnmarshaler”)。 (2认同)