gob简介

  • Gob 是Go语言自己以二进制形式序列化和反序列化程序数据的格式。在 encoder(编码器,也就是发送器)和 decoder(解码器,也就是接受器)之间交换的字节流数据。
  • 这种格式的数据简称为 Gob(即 Go binary 的缩写)。类似于 Python 的“pickle”和 Java 的“Serialization”。
  • 编码使用Encoder,解码使用Decoder。一种典型的应用场景就是RPC(remote procedure calls)。
  • 标准库gob是golang提供的“私有”的编解码方式,它的效率会比json,xml等更高,特别适合在Go语言程序间传递数据。

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import (
"bytes"
"encoding/gob"
"fmt"
)

type MsgData struct {
X, Y, Z int
Name string
}

var network bytes.Buffer //网络传递的数据载体

func senMsg()error {
fmt.Print("开始执行编码(发送端)")

enc := gob.NewEncoder(&network)
sendMsg:=MsgData{3, 4, 5, "jiangzhou"}
fmt.Println("原始数据:",sendMsg)
err := enc.Encode(&sendMsg)
fmt.Println("传递的编码数据为:",network)
return err
}

func revMsg()error {
var revData MsgData
dec:=gob.NewDecoder(&network)
err:= dec.Decode(&revData) //传递参数必须为地址
fmt.Println("解码之后的数据为:",revData)
return err
}

func main() {
// 通常encode和decode将绑定到网络连接,编码器和解码器将在不同的进程中运行。
err := senMsg()
if err!=nil {
fmt.Println("编码错误")
return
}
err = revMsg()
if err!=nil {
fmt.Println("解码错误")
return
}
}

demo2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main

import (
"encoding/gob"
"log"
"os"
)

type Address struct {
Type string
City string
Country string
}

type VCard struct {
FirstName string
LastName string
Addresses []*Address
Remark string
}

var content string

func main() {
pa := &Address{"private", "Aartselaar","Belgium"}
wa := &Address{"work", "Boom", "Belgium"}
vc := VCard{"Jan", "Kersschot", []*Address{pa,wa}, "none"}

fmt.Printf("%v: \n", vc) // {Jan Kersschot [0x126d2b80 0x126d2be0] none}:

// using an encoder:
file, _ := os.OpenFile("vcard.gob", os.O_CREATE|os.O_WRONLY, 0666)
defer file.Close()
enc := gob.NewEncoder(file)
err := enc.Encode(vc)
if err != nil {
log.Println("Error in encoding gob")
}
}

说明

  • Gob 并不是一种不同于 Go 的语言,而是在编码和解码过程中用到了 Go 的反射。
  • Gob 文件或流是完全自描述的:里面包含的所有类型都有一个对应的描述,并且总是可以用 Go 解码,而不需要了解文件的内容。
  • 只有可导出的字段会被编码,零值会被忽略。在解码结构体的时候,只有同时匹配名称和可兼容类型的字段才会被解码。当源数据类型增加新字段后,Gob 解码客户端仍然可以以这种方式正常工作:解码客户端会继续识别以前存在的字段。并且还提供了很大的灵活性,比如在发送者看来,整数被编码成没有固定长度的可变长度,而忽略具体的 Go 类型。

假如在发送者这边有一个有结构 T:

1
2
type T struct { X, Y, Z int }
var t = T{X: 7, Y: 0, Z: 8}

而在接收者这边可以用一个结构体 U 类型的变量 u 来接收这个值:

1
2
type U struct { X, Y *int8 }
var u U

在接收者中,X 的值是 7,Y 的值是 0(Y 的值并没有从 t 中传递过来,因为它是零值)

和 JSON 的使用方式一样,Gob 使用通用的 io.Writer 接口,通过 NewEncoder() 函数创建 Encoder 对象并调用 Encode();相反的过程使用通用的 io.Reader 接口,通过 NewDecoder() 函数创建 Decoder 对象并调用 Decode。