尝试解码nil值的gob导致EOF错误

时间:2016-06-22 08:02:41

标签: pointers go null gob

我需要使用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

1 个答案:

答案 0 :(得分:5)

您正在吞咽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。

但是为什么你不能用interface{}指针编码nil?引自encoding/gob的包文档:

  

指针不会被传输,但它们指向的东西会被传输;也就是说,这些值是扁平化的。

您的interface{}包含指针类型的值,但该指针为nil,它指向任何内容,不能展平。

以下是github上的相关问题:encoding/gob: panic on encoding nil pointer #3704

拉​​斯:

  gob并不知道指针是什么:一切都变平了。将nil指针放在interface {}值中会创建一个gob无法发送的非零值(它不是nil接口)(它无法表达&n'nil指针')。

Rob Pike:

  

正确。仅当具体值本身是可传输的时,才能传输接口值。至少就目前而言,这相当于说不能发送包含类型为nil指针的接口。