当前位置: 首页 > 工具软件 > GOB > 使用案例 >

Go:专属二进制编码方式Gob

施华奥
2023-12-01

Gob 是 Go 自己的以二进制形式序列化和反序列化程序数据的格式;可以在 encoding 包中找到。这种格式的数据简称为 Gob (即 Go binary 的缩写)。类似于 Python 的 “pickle” 和 Java 的 “Serialization”。

Gob 通常用于远程方法调用(RPCs,参见 15.9 的 rpc 包)参数和结果的传输,以及应用程序和机器之间的数据传输。 它和 JSON 或 XML 有什么不同呢?Gob 特定地用于纯 Go 的环境中,例如,两个用 Go 写的服务之间的通信。这样的话服务可以被实现得更加高效和优化。 Gob 不是可外部定义,语言无关的编码方式。因此它的首选格式是二进制,而不是像 JSON 和 XML 那样的文本格式。 Gob 并不是一种不同于 Go 的语言,而是在编码和解码过程中用到了 Go 的反射。

Gob 文件或流是完全自描述的:里面包含的所有类型都有一个对应的描述,并且总是可以用 Go 解码,而不需要了解文件的内容。

只有可导出的字段会被编码,零值会被忽略。在解码结构体的时候,只有同时匹配名称和可兼容类型的字段才会被解码。当源数据类型增加新字段后,Gob 解码客户端仍然可以以这种方式正常工作:解码客户端会继续识别以前存在的字段。并且还提供了很大的灵活性,比如在发送者看来,整数被编码成没有固定长度的可变长度,而忽略具体的 Go 类型。
 例1:数据结构与bytes.Buffer之间的转换(编码成字节切片)

package main

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

//准备编码的数据
type P struct {
    X, Y, Z int
    Name    string
}

//接收解码结果的结构
type Q struct {
    X, Y *int32
    Name string
}

func main() {
    //初始化一个数据
    data := P{3, 4, 5, "CloudGeek"}
    //编码后得到buf字节切片
    buf := encode(data)
    //用于接收解码数据
    var q *Q
    //解码操作
    q = decode(buf)
    //"CloudGeek": {3,4}
    fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y)

}

func encode(data interface{}) *bytes.Buffer {
    //Buffer类型实现了io.Writer接口
    var buf bytes.Buffer
    //得到编码器
    enc := gob.NewEncoder(&buf)
    //调用编码器的Encode方法来编码数据data
    enc.Encode(data)
    //编码后的结果放在buf中
    return &buf
}

func decode(data interface{}) *Q {
    d := data.(io.Reader)
    //获取一个解码器,参数需要实现io.Reader接口
    dec := gob.NewDecoder(d)
    var q Q
    //调用解码器的Decode方法将数据解码,用Q类型的q来接收
    dec.Decode(&q)
    return &q
}

例2:数据结构到文件的序列化和反序列化

package main

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

//试验用的数据类型
type Address struct {
    City    string
    Country string
}

//序列化后数据存放的路径
var filePath string

func main() {
    filePath = "./address.gob"
    encode()
    pa := decode()
    fmt.Println(*pa) //{Chengdu China}
}

//将数据序列号后写到文件中
func encode() {
    pa := &Address{"Chengdu", "China"}
    //打开文件,不存在的时候新建
    file, _ := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0666)
    defer file.Close()

    //encode后写到这个文件中
    enc := gob.NewEncoder(file)
    enc.Encode(pa)
}

//从文件中读取数据并反序列化
func decode() *Address {
    file, _ := os.Open(filePath)
    defer file.Close()

    var pa Address
    //decode操作
    dec := gob.NewDecoder(file)
    dec.Decode(&pa)
    return &pa
}

 类似资料: