12.11 用 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:

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

而在接收者這邊可以用一個結構體 U 類型的變量 u 來接收這個值:

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

// 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 編碼到文件:

// 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, 0666)
    defer file.Close()
    enc := gob.NewEncoder(file)
    err := enc.Encode(vc)
    if err != nil {
        log.Println("Error in encoding gob")
    }
}

練習 12.8degob.go

寫一個程序讀取 vcard.gob 文件,解碼並打印它的內容。

鏈接

results matching ""

    No results matching ""