【问题标题】:Golang Gob decoding does not decode array of []byte [duplicate]Golang Gob解码不解码[]byte数组[重复]
【发布时间】:2022-02-23 20:44:05
【问题描述】:

我正在尝试解码 Inv 结构,但解码相同的编码值会返回不同的值。

// inv struct
type Inv struct {
    AddrFrom string
    Type     int
    data     [][]byte  
}


inv := Inv{
    AddrFrom: nodeAddress,
    Type:     kind,
    data:     inventories,
}
data := GobEncode(inv)
var payload Inv
gob.NewDecoder(bytes.NewBuffer(data)).Decode(&payload)

这里的payload和inv有不同的值。当 inv 结构的解码数据字段长度为零时。

【问题讨论】:

    标签: go gob


    【解决方案1】:

    https://pkg.go.dev/encoding/gob

    chan 或 func 类型的结构字段被完全视为未导出的字段并被忽略。

    https://go.dev/ref/spec#Exported_identifiers

    可以导出标识符以允许从另一个包访问它。如果两者都导出一个标识符:

    • 标识符名称的第一个字符是 Unicode 大写字母(Unicode 类“Lu”);和
    • 标识符在包块中声明或者是字段名或方法名。

    不导出所有其他标识符。

    https://pkg.go.dev/encoding/gob#hdr-Types_and_Values

    Gob 可以按照优先顺序调用相应的方法,对实现 GobEncoder 或 encoding.BinaryMarshaler 接口的任何类型的值进行编码。

    Internally,gob 包依赖于 reflect 包,该包旨在尊重可见性原则。因此 gob 包不会自动处理这些字段,它需要您编写专门的实现。


    https://pkg.go.dev/encoding/gob#GobEncoder

    GobEncoder 是描述数据的接口,它为传输到 GobDecoder 的编码值提供自己的表示。实现 GobEncoder 和 GobDecoder 的类型可以完全控制其数据的表示,因此可能包含私有字段、通道和函数等通常无法在 gob 流中传输的内容。

    例子

    package main
    
    import (
        "bytes"
        "encoding/gob"
        "fmt"
        "log"
    )
    
    // The Vector type has unexported fields, which the package cannot access.
    // We therefore write a BinaryMarshal/BinaryUnmarshal method pair to allow us
    // to send and receive the type with the gob package. These interfaces are
    // defined in the "encoding" package.
    // We could equivalently use the locally defined GobEncode/GobDecoder
    // interfaces.
    type Vector struct {
        x, y, z int
    }
    
    func (v Vector) MarshalBinary() ([]byte, error) {
        // A simple encoding: plain text.
        var b bytes.Buffer
        fmt.Fprintln(&b, v.x, v.y, v.z)
        return b.Bytes(), nil
    }
    
    // UnmarshalBinary modifies the receiver so it must take a pointer receiver.
    func (v *Vector) UnmarshalBinary(data []byte) error {
        // A simple encoding: plain text.
        b := bytes.NewBuffer(data)
        _, err := fmt.Fscanln(b, &v.x, &v.y, &v.z)
        return err
    }
    
    // This example transmits a value that implements the custom encoding and decoding methods.
    func main() {
        var network bytes.Buffer // Stand-in for the network.
    
        // Create an encoder and send a value.
        enc := gob.NewEncoder(&network)
        err := enc.Encode(Vector{3, 4, 5})
        if err != nil {
            log.Fatal("encode:", err)
        }
    
        // Create a decoder and receive a value.
        dec := gob.NewDecoder(&network)
        var v Vector
        err = dec.Decode(&v)
        if err != nil {
            log.Fatal("decode:", err)
        }
        fmt.Println(v)
    
    }
    

    由于字段类型已经是字节片,您确实只是遇到了可见性访问问题和专用所需的编组实现,虽然因为您也可以导出该字段而存在争议,但应该很简单。

    【讨论】:

    • 感谢您的回答,原来这是一个可见性问题。没有正确阅读文档我的错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 2021-08-04
    • 2018-09-27
    • 2021-05-10
    • 2021-06-14
    • 2017-09-23
    • 2019-09-12
    相关资源
    最近更新 更多