一尘不染

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

go

当值之一为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

在这种情况下,料滴是否有充分的理由失败?似乎两个明显的选择之一都比失败更可取:1)不对任何键值为零的键进行编码,或者2)即使值为零也对所有键进行编码。在当前状态下,最佳实践是递归地扫描我的结构以查看是否有任何nil映射值,如果有则删除这些键吗?如果需要进行此检查,则似乎应该由编码/
gob包而不是用户负责。

此外,规则不是简单地“ gob无法对键值为nil的映射进行编码”,因为如果值类型是slice,则可以接受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
    }
}

阅读 340

收藏
2020-07-02

共1个答案

一尘不染

gob编码流没有指针的概念。如果对诸如的指针值进行编码*int,则将发送指向的值,即type的值int。如果需要,可以在解码器端将此转换反向,例如,如果int*int要为其设置值的流中找到一个值,则将设置一个指针(类型为*int),指向已解码的int值。

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

gob上也有记录:基础知识:

指针不被传输,但是指针所指向的事物被传输。即,将值展平。 不允许使用零指针,因为它们没有值。

2020-07-02