Gob无法使用nil指针值对地图进行编码

时间:2018-06-06 16:18:10

标签: pointers go gob

如果其中一个值为nil,当我尝试将地图编码为指针时,Gob的Encode会返回错误。这似乎与文档相矛盾(但我可能会误解其含义):

  

在切片和数组以及地图中,即使所有元素都为零,也会传输所有元素,甚至是零值元素。

代码:

package main

import (
    "bytes"
    "encoding/gob"
)

type Dog struct {
    Name string
}

func main() {
    m0 := make(map[string]*Dog)
    m0["apple"] = nil

    // Encode m0 to bytes
    var network bytes.Buffer
    enc := gob.NewEncoder(&network)
    err := enc.Encode(m0)
    if err != nil {
        panic(err) // Output: panic: gob: encodeReflectValue: nil element
    }
}

输出:

panic: gob: encodeReflectValue: nil element

在这种情况下,gob是否有充分理由失败?似乎两个显而易见的选项中的任何一个都优于失败:1)不编码具有零值的任何键或2)编码所有键,即使值是零值。对于当前的状态,最好的做法是递归扫描我的结构以查看是否有任何nil映射值,如果是这样就删除这些键?如果需要进行此检查,似乎应该由编码/ gob包负责,而不是用户。

此外,规则不仅仅是“gob无法对键值为nil的地图进行编码”,因为如果值类型是切片,则接受nil:

func main() {
    m0 := make(map[string][]string)
    m0["apple"] = nil

    // Encode m0 to bytes
    var network bytes.Buffer
    enc := gob.NewEncoder(&network)
    err := enc.Encode(m0) // err is nil
    if err != nil {
        panic(err) // doesn't panic
    }
}

1 个答案:

答案 0 :(得分:3)

gob编码的流没有指针的概念。如果对*int之类的指针值进行编码,则会发送指向的值,即类型为int的值。如果需要,在解码器侧反转该变换,例如,如果在要为其设置int值的流中找到*int值,则将设置指向已解码*int的指针(类型为int)值。

因此,如果指针值本身为nil,则gob包不能编码而不是指针值,nil指针指向任何值。取消引用nil指针是运行时的恐慌。

gob: Basics:

也记录了这一点
  

指针不会被传输,但它们指向的东西会被传输;也就是说,这些值是扁平化的。 不允许使用Nil指针,因为它们没有任何价值。