|
@@ -0,0 +1,134 @@
|
|
|
|
|
+# 用 Gob 传输数据
|
|
|
|
|
+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 类型。
|
|
|
|
|
+
|
|
|
|
|
+假如在发送者这边有一个有结构 T:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+type T struct { X, Y, Z int }
|
|
|
|
|
+var t = T{X: 7, Y: 0, Z: 8}
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+而在接收者这边可以用一个结构体 U 类型的变量 u 来接收这个值:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+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`。我们把示例 12.12 的信息写进名为 vcard.gob 的文件作为例子。这会产生一个文本可读数据和二进制数据的混合,当你试着在文本编辑中打开的时候会看到。
|
|
|
|
|
+
|
|
|
|
|
+在示例 12.18 中你会看到一个编解码,并且以字节缓冲模拟网络传输的简单例子:
|
|
|
|
|
+
|
|
|
|
|
+示例 12.18 [gob1.go](examples/chapter_12/gob1.go):
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+// gob1.go
|
|
|
|
|
+package main
|
|
|
|
|
+
|
|
|
|
|
+import (
|
|
|
|
|
+ "bytes"
|
|
|
|
|
+ "fmt"
|
|
|
|
|
+ "encoding/gob"
|
|
|
|
|
+ "log"
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+type P struct {
|
|
|
|
|
+ X, Y, Z int
|
|
|
|
|
+ Name string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+type Q struct {
|
|
|
|
|
+ X, Y *int32
|
|
|
|
|
+ Name string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func main() {
|
|
|
|
|
+ // Initialize the encoder and decoder. Normally enc and dec would be
|
|
|
|
|
+ // bound to network connections and the encoder and decoder would
|
|
|
|
|
+ // run in different processes.
|
|
|
|
|
+ var network bytes.Buffer // Stand-in for a network connection
|
|
|
|
|
+ enc := gob.NewEncoder(&network) // Will write to network.
|
|
|
|
|
+ dec := gob.NewDecoder(&network) // Will read from network.
|
|
|
|
|
+ // Encode (send) the value.
|
|
|
|
|
+ err := enc.Encode(P{3, 4, 5, "Pythagoras"})
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Fatal("encode error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ // Decode (receive) the value.
|
|
|
|
|
+ var q Q
|
|
|
|
|
+ err = dec.Decode(&q)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Fatal("decode error:", err)
|
|
|
|
|
+ }
|
|
|
|
|
+ fmt.Printf("%q: {%d,%d}\n", q.Name, *q.X, *q.Y)
|
|
|
|
|
+}
|
|
|
|
|
+// Output: "Pythagoras": {3,4}
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+示例 12.19[gob2.go](examples/chapter_12/gob2.go) 编码到文件:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+// gob2.go
|
|
|
|
|
+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, 0)
|
|
|
|
|
+ defer file.Close()
|
|
|
|
|
+ enc := gob.NewEncoder(file)
|
|
|
|
|
+ err := enc.Encode(vc)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ log.Println("Error in encoding gob")
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**练习 12.8**:[degob.go](exercises/chapter_12/degob.go):
|
|
|
|
|
+
|
|
|
|
|
+写一个程序读取 vcard.gob 文件,编码并打印它的内容。
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+## 链接
|
|
|
|
|
+
|
|
|
|
|
+- [目录](directory.md)
|
|
|
|
|
+- 上一节:[XML 数据格式](12.10.md)
|
|
|
|
|
+- 下一节:[Go 中的密码学](12.12.md)
|