gob 恐慌解码接口
gob panics decoding an interface
我有一个包含未导出字段的结构,应该进行 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 接口注释掉,一切都会好起来的。
我是不是漏掉了什么重要的东西?因为所描述的行为对我来说似乎很奇怪
在您的情况下,您需要定义您期望解码转储到接口值中的 "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.GobEncoder
和 gob.GobDecoder
接口,根据定义,它们负责编码/解码。如果一个类型实现了这些接口,解码器将不会尝试使用传输类型解码值,而是调用目标值的 GobDecode()
方法,如果需要创建零值。
由于您将 nil
值传递给 Decoder.Decode()
,解码器需要创建一个零值,但它不知道要实例化什么类型,因为您传递的值是一个指向接口的指针。您不能创建接口类型的值,只能创建满足特定接口的具体类型的值。
您不能在 Incer
界面中包含 gob.GobEncoder
和 gob.GobDecoder
。我知道您想确保实现确实实现了它们,但是如您所见,您将无法将它们解码为 "general" Incer
接口值。此外,我什至不认为有必要将它们包含在 Incer
中:gob.GobEncoder
和 gob.GobDecoder
并不是使它们可传输的唯一方法,还有 encoding.BinaryMarshaler
and encoding.BinaryUnmarshaler
由 encoding/gob
包检查。
我有一个包含未导出字段的结构,应该进行 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 接口注释掉,一切都会好起来的。
我是不是漏掉了什么重要的东西?因为所描述的行为对我来说似乎很奇怪
在您的情况下,您需要定义您期望解码转储到接口值中的 "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.GobEncoder
和 gob.GobDecoder
接口,根据定义,它们负责编码/解码。如果一个类型实现了这些接口,解码器将不会尝试使用传输类型解码值,而是调用目标值的 GobDecode()
方法,如果需要创建零值。
由于您将 nil
值传递给 Decoder.Decode()
,解码器需要创建一个零值,但它不知道要实例化什么类型,因为您传递的值是一个指向接口的指针。您不能创建接口类型的值,只能创建满足特定接口的具体类型的值。
您不能在 Incer
界面中包含 gob.GobEncoder
和 gob.GobDecoder
。我知道您想确保实现确实实现了它们,但是如您所见,您将无法将它们解码为 "general" Incer
接口值。此外,我什至不认为有必要将它们包含在 Incer
中:gob.GobEncoder
和 gob.GobDecoder
并不是使它们可传输的唯一方法,还有 encoding.BinaryMarshaler
and encoding.BinaryUnmarshaler
由 encoding/gob
包检查。