encoding/gob in the learning of Go language standard library – the management of Go language Gob flow
正文根据实际情况对原文进行调整
Gob 包用于管理 gob 流。它可以在编码器(发送器)和解码器(接收器)之间发送二进制数据流。一般用于传递远程程序调用的参数和结果。例如,net/rpc 包对此很有用。下面我们来学习一下gob标准库的使用,希望对你有所帮助。
主要功能介绍gob 和 json 的打包方法一样。发送方使用 Encoder 对数据结构进行编码。接收方接收到消息后,使用解码器将序列化后的数据转化为局部变量。与json编码格式相比,gob编码可以实现json不支持的struct方法的序列化。使用 gob 包将结构体序列化并保存在本地也非常方便。
编码数据将在传输前进行编码。与编码相关的三种方法:
- NewDecoder:func NewEncoder(w io.Writer) *Encoder,NewEncode 返回一个 Encoder 类型的指针,该指针将编码的数据写入 w 中
- Encode:func (enc *Encoder) Encode(e interface{}) error,Encode 方法编码在发送前对 e 进行编码,并且确保所有类型的信息首先发送
- EncodeValue:func (enc *Encoder) EncodeValue(value reflect.Value) error,EncodeValue 方法编码和发送值代表的数据,并且确保所有类型的信息首先发送
接收到数据后,需要对数据进行解码。
- NewDecoder:func NewDecoder(r io.Reader) *Decoder,该方法染回一个从 r 中读取数据的解码器,如果 r 不满足 io.ByteReader类型,接口将会将 r 包裹成 bufio.Reader类型
- Decode:func (dec *Decoder) Decode(e interface{}) error
- 解码从输入流中读取下一个并将值存储在 e 中。
- 如果 e 是 nil,则该值会被遗弃,否则 e 将会是一个可以接收该类型值的指针。
- 如果输入结束了,这个方法返回一个 io.EOF并且不会改变 e(指向的值)
- DecodeValue:func (dec *Decoder) DecodeValue(v reflect.Value) error
- DecodeValue 从输入流中读取下一个值,如果 V 是 reflect.Value 类型的零值(v.Kind() == Invalid)则被丢弃,否则这个值存放在 V 中。
- 在这种情况下,V 代表了一个指向实际值的非零指针,或者一个可写的 reflect.Value 类型(v.CanSet() 为真)
- 如果输入结束了,这个方法返回一个 io.EOF并且不会改变 e(指向的值)
这里需要明确一下,gob只能在golang中使用。因此,在实际的项目开发过程中,如果与其他终端或其他语言打交道,gob是不允许的。我们将使用 json。
优势Gob 流是自解码的。流中的所有数据都带有前缀(在预定义类型的集合中)以指示其类型。指针不传递,而是传递值;也就是说,数据被扁平化。递归类型可以很好的工作,但递归值(例如,值中的成员直接/间接指向该值)可能会出错。这个问题将来可能会得到解决。
要使用 gob,您首先创建一个编码器并为其提供一系列数据:一个值或指向实际数据的指针。编码器确保发送所有必要的类型信息。在接收端,解码器从编码数据流中恢复数据并将其填充到局部变量中。
gob 编码和解码不需要发送器和接收器的结构相同。以下是官方文件的翻译:
// 定义一个结构体
struct { A, B int }
// 下面的数据类型可以被发送和被接收:
struct { A, B int } // 一样
*struct { A, B int } // 额外的结构体指针
struct { *A, **B int } // 额外的字段的指针
struct { A, B int64 } // 不同的类型
// 下面的类型可以被接收:
struct { A, B int } // 一样
struct { B, A int } // 顺序不重要,通过名字来匹配
struct { A, B, C int } // 多余的字段 C 会被忽略
struct { B int } // 缺少的 A 字段会被忽略;数据会被遗弃
struct { B, C int } // 缺少的 A 字段会被忽略; 多余的 C 字段会被忽略.
// 以下格式有问题:
struct { A int; B uint } // B 的签名改变了
struct { A int; B float } // B 的类型改变了
struct { } // 没有共同的字段名
struct { C, D int } // 没有共同的字段名
gob 编码实例译者注:总而言之解码和编码相匹配就是遵循以下几个标准
- 存在指针可以(不论是结构体指针,还是字段指针),go 提供了自动解指针的能力
- 缺少或者存在额外字段可以,但是至少(发送和接收的)结构中存在一个相匹配的字段
这里以官网 https://golang.org/pkg/encoding/gob/ 为例:
基础package main
import (
"bytes"
"encoding/gob"
"fmt"
"log"
)
type P struct {
X, Y, Z int
Name string
}
type Q struct {
X, Y *int32
Name string
}
// 这是一个基础的创建编码器的用例,编码数据,然后用解码器来接收
func main() {
// 初始化编码器,并且创建一个解码器的实例
var network bytes.Buffer // 标准输入
enc := gob.NewEncoder(&network) // 编码
dec := gob.NewDecoder(&network) // 解码
// 编码器发送数据
err := enc.Encode(P{3, 4, 5, "Pythagoras"})
if err != nil {
log.Fatal("encode error:", err)
}
err = enc.Encode(P{1782, 1841, 1922, "Treehouse"})
if err != nil {
log.Fatal("encode error:", err)
}
// 解码器接收数据
var q Q
err = dec.Decode(&q)
if err != nil {
log.Fatal("decode error 1:", err)
}
fmt.Printf("%q: {%d, %d}n", q.Name, *q.X, *q.Y)
err = dec.Decode(&q)
if err != nil {
log.Fatal("decode error 2:", err)
}
fmt.Printf("%q: {%d, %d}n", q.Name, *q.X, *q.Y)
}
译者图
控制台
PS D:codego_projectstudyencodinggob> go run .
"Pythagoras": {3, 4}
"Treehouse": {1782, 1841}



