gob 恐慌解码接口

gob panics decoding an interface

我有一个包含未导出字段的结构,应该进行 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 接口注释掉,一切都会好起来的。

我是不是漏掉了什么重要的东西?因为所描述的行为对我来说似乎很奇怪

在您的情况下,您需要定义您期望解码转储到接口值中的 "layout" 内存。当你声明

var v Incer

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

var v Incer
v = &A{}

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

这是example provided in the gob documentation

问题出在Incer接口实现了一个特殊的接口,特殊给encoding/gob包:gob.GobDecoder.

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

type Incer interface {
    Inc()
}

所以解码成功

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

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

您不能在 Incer 界面中包含 gob.GobEncodergob.GobDecoder。我知道您想确保实现确实实现了它们,但是如您所见,您将无法将它们解码为 "general" Incer 接口值。此外,我什至不认为有必要将它们包含在 Incer 中:gob.GobEncodergob.GobDecoder 并不是使它们可传输的唯一方法,还有 encoding.BinaryMarshaler and encoding.BinaryUnmarshalerencoding/gob 包检查。