【问题标题】:Gob can't encode map with a nil pointer valueGob 无法使用 nil 指针值对地图进行编码
【发布时间】:2018-06-06 16:18:09
【问题描述】:

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

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

代码:

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 映射值,如果有,则删除这些键的最佳做法是什么?如果需要这个检查,似乎应该是 encoding/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
    }
}

【问题讨论】:

    标签: pointers go gob


    【解决方案1】:

    gob 编码流没有指针的概念。如果对*int等指针值进行编码,则会发送指向的值,即int类型的值。如果需要,这种转换会在解码器端进行反转,例如如果在要设置*int 值的流中找到int 值,则将设置一个指针(*int 类型)指向解码后的int 值。

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

    这也记录在gob: Basics:

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

    【讨论】:

    • 错误输出真的比忽略这些值更好吗?就目前的情况而言,递归扫描我的结构以查看是否有任何 nil 映射值,如果有,则删除这些键的最佳做法是什么?如果需要这个检查,似乎应该是 encoding/gob 包的责任,而不是用户。
    • @rampatowl 首先,您不应该在地图中存储nil 指针。它很少有用,如果你想用gob对其进行编码,则禁止有这样的值。
    猜你喜欢
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-08-15
    • 2012-12-16
    相关资源
    最近更新 更多