gob包("encoding/gob")管理gob流——在encoder(编码器,也就是发送器)和decoder(解码器,也就是接受器)之间交换的字节流数据(gob 就是 go binary的缩写)。一般用于传递远端程序调用(RPC)的参数和结果。
要使用gob,要先创建一个编码器(调用NewEncoder()方法),并向其提供一系列数据;然后在接收端,通过调用NewDecoder()方法创建一个解码器,它从数据流中恢复数据并将它们填写进本地变量里。下面会通过几个例子进行说明。
发送端和接收端的值/类型不需要严格匹配。对结构体来说,某一字段(通过字段名进行识别)如果发送端有而接收端没有,会被忽略;接收端有而发送端没有的字段也会被忽略;发送端和接收端都有的字段其类型必须是可兼容的;发送端和接收端都会在gob流和实际go类型之间进行必要的指针取址/寻址工作。举例如下:
下面是发送端的承载数据的结构体:
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,会丢弃A的值
struct { B, C int }// 忽略缺少的字段A,忽略多出的字段C
但尝试发送给如下类型的话就会导致错误:
struct { A int; B uint }// B字段改变了符号类型
struct { A int; B float }// B字段改变了类型
struct { }// 无共同字段名
struct { C, D int }// 无共同字段名
示例1:
type P struct { X, Y, Z int Name string } type Q struct { X, Y *int32 Name string } type R struct { Y, W int } // This example shows the basic usage of the package: Create an encoder, // transmit some values, receive them with a decoder. func GobBasic() { // 初始化 encoder 和 decoder var buf bytes.Buffer encoder := gob.NewEncoder(&buf) // will write to buf decoder := gob.NewDecoder(&buf) // will read from buf // Encode (send) some values err := encoder.Encode(P{X: 3, Y: 4, Z: 5, Name: "hello"}) if err != nil { log.Fatal("Encode error:",err) } // Decode (receive) and print the values //var q Q //err = decoder.Decode(&q) //if err != nil { // log.Fatal("Decode error:",err) //} // //// 注意,不能写成 q.X,因为在接收方,定义的是 int型 指针 //// *(q.X) 与 *q.Y 结果相同,但前者语义更加明确 //fmt.Printf("%d %d %s\n", *(q.X), *q.Y, q.Name) //var p P //err = decoder.Decode(&p) //if err != nil { // log.Fatal("Decode error:",err) //} //// 这里的接收方和传入方格式完全一致 //fmt.Printf("%d %d %d %s\n", p.X, p.Y, p.Z, p.Name) var r R err = decoder.Decode(&r) if err != nil { log.Fatal("Decode error:",err) } //fmt.Printf("%d %d %d %s\n", r.X, r.Y, r.Z, r.Name) // 会输出如下:因为接收端是根据字段名称进行匹配的 // r.X undefined (type R has no field or method X) // r.Z undefined (type R has no field or method Z) // r.Name undefined (type R has no field or method Name) fmt.Printf("%d\n", r.Y) // ok }
示例2: