Go语言学习之encoding/gob包(The way to go)

生命不止,继续 go go go !!!

为了让某个数据结构能够在网络上传输或能够保存至文件,它必须被编码然后再解码。当然,已经有许多可用的编码方式了:JSON,XML,Google 的 protocol buffers,等等。而现在,又多了一种,由 Go 的 gob 包提供的方式。

gob是Golang包自带的一个数据结构序列化的编码/解码工具。
编码使用Encoder,解码使用Decoder。一种典型的应用场景就是RPC(remote procedure calls)。

gob和json的pack之类的方法一样,由发送端使用Encoder对数据结构进行编码。在接收端收到消息之后,接收端使用Decoder将序列化的数据变化成本地变量。

golang可以通过json或gob来序列化struct对象,虽然json的序列化更为通用,但利用gob编码可以实现json所不能支持的struct的方法序列化,利用gob包序列化struct保存到本地也十分简单。

Package gob manages streams of gobs - binary values exchanged between an Encoder (transmitter) and a Decoder (receiver). A typical use is transporting arguments and results of remote procedure calls (RPCs) such as those provided by package "net/rpc".

介绍几个方法:

func Register

func Register(value interface{})

注册
Register records a type, identified by a value for that type, under its internal type name.

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a new decoder that reads from the io.Reader.

func (*Decoder) Decode

func (dec *Decoder) Decode(e interface{}) error

Decode reads the next value from the input stream and stores it in the data represented by the empty interface value.

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns a new encoder that will transmit on the io.Writer.

func (*Encoder) Encode

func (enc *Encoder) Encode(e interface{}) error

Encode transmits the data item represented by the empty interface value, guaranteeing that all necessary type information has been transmitted first.

gob的优势
这里需要明确一点,gob只能用在golang中,所以在实际工程开发过程中,如果与其他端,或者其他语言打交道,那么gob是不可以的,我们就要使用json了。
Gob is much more preferred when communicating between Go programs. However, gob is currently supported only in Go and, well, C, so only ever use that when you’re sure no program written in any other programming language will try to decode the values.

gob的优势就是:发送方的结构和接受方的结构并不需要完全一致,例如定义一个结构体:

struct { A, B int }

下面的类型都是可以发送、接收的:

struct { A, B int } // the same
*struct { A, B int }    // extra indirection of the struct
struct { *A, **B int }  // extra indirection of the fields
struct { A, B int64 }   // different concrete value type; see below

以下可以接收:

struct { A, B int } // the same
struct { B, A int } // ordering doesn't matter; matching is by name
struct { A, B, C int }  // extra field (C) ignored
struct { B int }    // missing field (A) ignored; data will be dropped
struct { B, C int } // missing field (A) ignored; extra field (C) ignored.

下面的格式是有问题的:

struct { A int; B uint }    // change of signedness for B
struct { A int; B float }   // change of type for B
struct { }          // no field names in common
struct { C, D int }     // no field names in common

应用
再次强调,注意看官方的文档和例子:
https://golang.org/pkg/encoding/gob/
为我们提供了非常好的三个例子,可以学习参考!!

例1:

package main

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

type MyFace interface {
    A()
}

type Cat struct{}
type Dog struct{}

func (c *Cat) A() {
    fmt.Println("Meow")
}

func (d *Dog) A() {
    fmt.Println("Woof")
}

func init() {
    // This type must match exactly what youre going to be using,
    // down to whether or not its a pointer
    gob.Register(&Cat{})
    gob.Register(&Dog{})
}

func main() {
    network := new(bytes.Buffer)
    enc := gob.NewEncoder(network)

    var inter MyFace
    inter = new(Cat)

    // Note: pointer to the interface
    err := enc.Encode(&inter)
    if err != nil {
        panic(err)
    }

    inter = new(Dog)
    err = enc.Encode(&inter)
    if err != nil {
        panic(err)
    }

    // Now lets get them back out
    dec := gob.NewDecoder(network)

    var get MyFace
    err = dec.Decode(&get)
    if err != nil {
        panic(err)
    }

    // Should meow
    get.A()

    err = dec.Decode(&get)
    if err != nil {
        panic(err)
    }

    // Should woof
    get.A()

}

输出:
Meow
Woof

例2:gob包实现的序列化struct对象保存到本地,利用gob反序列化本地的struct对象

package main

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

const file = "./test.gob"

type User struct {
    Name, Pass string
}

func main() {
    var datato = &User{"Donald", "DuckPass"}
    var datafrom = new(User)

    err := Save(file, datato)
    Check(err)
    err = Load(file, datafrom)
    Check(err)
    fmt.Println(datafrom)
}

// Encode via Gob to file
func Save(path string, object interface{}) error {
    file, err := os.Create(path)
    if err == nil {
        encoder := gob.NewEncoder(file)
        encoder.Encode(object)
    }
    file.Close()
    return err
}

// Decode Gob file
func Load(path string, object interface{}) error {
    file, err := os.Open(path)
    if err == nil {
        decoder := gob.NewDecoder(file)
        err = decoder.Decode(object)
    }
    file.Close()
    return err
}

func Check(e error) {
    if e != nil {
        _, file, line, _ := runtime.Caller(1)
        fmt.Println(line, "\t", file, "\n", e)
        os.Exit(1)
    }
}

输出:
&{Donald DuckPass}

你可能感兴趣的:(go语言,gob)