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