Gob 无法使用 nil 指针值对映射进行编码

ram*_*owl 2 pointers go gob

当我尝试将映射编码为指针(如果其中一个值为零)时,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
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

panic: gob: encodeReflectValue: nil element
Run Code Online (Sandbox Code Playgroud)

在这种情况下,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
    }
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

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

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

这也记录在gob:基础知识:

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