gob 试图解码 nil 值导致 EOF 错误
gob attempting to decode nil value results in EOF error
我需要使用 gob
来编码一些数据,但是,我发现 "type nil" 无法正确处理(转到 1.6.2)
https://play.golang.org/p/faypK8uobF
package main
import (
"bytes"
"encoding/gob"
"log"
)
type T struct {
A int
}
func init() {
gob.Register(map[string]interface{}{})
gob.Register(new(T))
}
func main() {
bys := bytes.NewBuffer(nil)
gob.NewEncoder(bys).Encode(map[string]interface{}{
"v": (*T)(nil),
})
out := map[string]interface{}{}
if err := gob.NewDecoder(bys).Decode(&out); err != nil {
log.Panic(err)
}
return
}
输出:
panic: EOF
您正在吞下 Encoder.Encode()
返回的 error
:
err := gob.NewEncoder(bys).Encode(map[string]interface{}{
"v": (*T)(nil),
})
if err != nil {
fmt.Println(err)
}
输出:
gob: gob: cannot encode nil pointer of type *main.T inside interface
这是由未导出的方法生成的 Encoder.encodeInterface()
。引用自 encode.go
,未导出方法 Encoder.encodeInterface()
:
// Gobs can encode nil interface values but not typed interface
// values holding nil pointers, since nil pointers point to no value.
elem := iv.Elem()
if elem.Kind() == reflect.Ptr && elem.IsNil() {
errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type())
}
因此您的 Encoder.Encode()
失败了,它没有向其输出(即 bys
缓冲区)写入任何内容,因此尝试从中读取(解码)任何内容都会导致 EOF。
但是为什么不能对包含 nil
指针的 interface{}
值进行编码?引用 encoding/gob
的包文档:
Pointers are not transmitted, but the things they point to are transmitted; that is, the values are flattened.
你的 interface{}
包含一个指针类型的值,但是那个指针是 nil
,它指向任何东西,它不能被展平。
github 上有一个相关问题:encoding/gob: panic on encoding nil pointer #3704
拉斯:
gob doesn't know what a pointer is: everything gets flattened. Putting a nil pointer in an interface{} value creates a non-zero value (it's not the nil interface) that gob cannot send (it can't express 'nil pointer').
罗伯·派克:
Correct. An interface value can be transmitted only if the concrete value itself is transmittable. At least for now, that's equivalent to saying that interfaces holding typed nil pointers cannot be sent.
我需要使用 gob
来编码一些数据,但是,我发现 "type nil" 无法正确处理(转到 1.6.2)
https://play.golang.org/p/faypK8uobF
package main
import (
"bytes"
"encoding/gob"
"log"
)
type T struct {
A int
}
func init() {
gob.Register(map[string]interface{}{})
gob.Register(new(T))
}
func main() {
bys := bytes.NewBuffer(nil)
gob.NewEncoder(bys).Encode(map[string]interface{}{
"v": (*T)(nil),
})
out := map[string]interface{}{}
if err := gob.NewDecoder(bys).Decode(&out); err != nil {
log.Panic(err)
}
return
}
输出:
panic: EOF
您正在吞下 Encoder.Encode()
返回的 error
:
err := gob.NewEncoder(bys).Encode(map[string]interface{}{
"v": (*T)(nil),
})
if err != nil {
fmt.Println(err)
}
输出:
gob: gob: cannot encode nil pointer of type *main.T inside interface
这是由未导出的方法生成的 Encoder.encodeInterface()
。引用自 encode.go
,未导出方法 Encoder.encodeInterface()
:
// Gobs can encode nil interface values but not typed interface
// values holding nil pointers, since nil pointers point to no value.
elem := iv.Elem()
if elem.Kind() == reflect.Ptr && elem.IsNil() {
errorf("gob: cannot encode nil pointer of type %s inside interface", iv.Elem().Type())
}
因此您的 Encoder.Encode()
失败了,它没有向其输出(即 bys
缓冲区)写入任何内容,因此尝试从中读取(解码)任何内容都会导致 EOF。
但是为什么不能对包含 nil
指针的 interface{}
值进行编码?引用 encoding/gob
的包文档:
Pointers are not transmitted, but the things they point to are transmitted; that is, the values are flattened.
你的 interface{}
包含一个指针类型的值,但是那个指针是 nil
,它指向任何东西,它不能被展平。
github 上有一个相关问题:encoding/gob: panic on encoding nil pointer #3704
拉斯:
gob doesn't know what a pointer is: everything gets flattened. Putting a nil pointer in an interface{} value creates a non-zero value (it's not the nil interface) that gob cannot send (it can't express 'nil pointer').
罗伯·派克:
Correct. An interface value can be transmitted only if the concrete value itself is transmittable. At least for now, that's equivalent to saying that interfaces holding typed nil pointers cannot be sent.