我有一个带有未导出字段的结构,应该对其进行 gob 编码和解码。
说:
type A struct {
s int
}
func (a *A) Inc() {
a.s++
}
Run Code Online (Sandbox Code Playgroud)
显然在这种情况下我需要实现gob.GobEncoder和gob.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 接口,一切都会变得很好。
我错过了什么重要的事情吗?因为所描述的行为对我来说似乎很奇怪
问题在于该Incer接口实现了一个特殊的接口,对于encoding/gob包来说是特殊的:gob.GobDecoder。
如果您的Incer界面仅包含Inc()方法,那么它将起作用,因为 gob 解码器看到您正在解码为接口类型,并且它将使用传输的类型来解码该值并在运行时检查解码后的值(其类型包含在并在流中传输)实现目标接口类型,在这种情况下它将:
type Incer interface {\n Inc()\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这样解码就成功了。
\n\n如果Incer接口还嵌入了gob.GobEncoder和gob.GobDecoder接口,则根据定义,它们是 \xe2\x80\x93\xe2\x80\x93 负责进行编码/解码。如果类型实现这些接口,解码器将不会尝试使用传输的类型解码值,而是调用GobDecode()目标值的方法,并在需要时创建零值。
由于您将nil值传递给Decoder.Decode(),解码器需要创建一个零值,但它不知道要实例化什么类型,因为您传递的值是指向接口的指针。您不能创建接口类型的值,只能创建可以满足某些接口的具体类型的值。
您不能在界面中包含gob.GobEncoder和。我知道您想确保实现确实实现了它们,但是 \xe2\x80\x93 正如您所看到的 \xe2\x80\x93 您将无法将它们解码为“通用”接口值。另外,我什至不认为有必要将它们包含在:中,并且并不是使它们可传输的唯一方法,还有由包检查的和。gob.GobDecoderIncerIncerIncergob.GobEncodergob.GobDecoderencoding.BinaryMarshalerencoding.BinaryUnmarshalerencoding/gob