zoukankan      html  css  js  c++  java
  • 转: gob编解码

    要让数据对象能在网络上传输或存储,我们需要进行编码和解码。现在比较流行的编码方式有JSON,XML等。然而,Go在gob包中为我们提供了另一种方式,该方式编解码效率高于JSON。gob是Golang包自带的一个数据结构序列化的编码/解码工具

    源和目的地值/类型不需要完全对应。在接收变量中,但从发送类型或值丢失的字段将在目标中被忽略。如果在两个字段中都存在同名的字段,则它们的类型必须兼容。接收器和发送器都会做所有必要的间接和迂回,以在实际值和实际值之间转换。

    struct { A, B int }
    can be sent from or received into any of these Go types:

    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
    It may also be received into any of these:

    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.
    Attempting to receive into these types will draw a decode error:

    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
    例子:

    package main

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

    type Person struct {
    Name string
    Age int
    Action Run
    }

    type Run struct {
    Speed int
    }

    func main() {
    var dao bytes.Buffer

    var encoder = gob.NewEncoder(&dao)
    var decoder = gob.NewDecoder(&dao)

    p := Person{Name:"chen",Age:18,Action:Run{80}}

    err := encoder.Encode(&p)
    if err != nil{
    panic(err)
    }

    fmt.Println(dao.String())

    var d Person
    err = decoder.Decode(&d)
    if err != nil{
    panic(err)
    }

    fmt.Println(d)
    }
    如果Encode/Decode类型是interface或者struct中某些字段是interface{}的时候,需要在gob中注册interface可能的所有实现或者可能类型,不然会报:panic: gob: type not registered for interface: main.Run错误

    例子2 编解码的struct中某些字段是interface{}的时候

    package main

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

    func init() {
    gob.Register(&Run{})//必须在encoding/gob编码解码前进行注册
    }

    //panic: gob: type not registered for interface: main.Run
    type Person struct {
    Name string
    Age int
    Action interface{}
    }

    type Run struct {
    Speed int
    }

    func main() {
    var dao bytes.Buffer

    encoder := gob.NewEncoder(&dao)
    decoder := gob.NewDecoder(&dao)

    p := Person{Name:"chen",Age:18,Action:Run{80}}

    err := encoder.Encode(&p)
    if err != nil{
    panic(err)
    }

    fmt.Println(dao.String())

    var d Person
    err = decoder.Decode(&d)
    if err != nil{
    panic(err)
    }

    fmt.Println(d)

    }
    例子3 编解码的类型是interface

    package main

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

    func init() {
    gob.Register(&Person{})//必须在encoding/gob编码解码前进行注册
    gob.Register(&Dog{})
    }

    type Actioner interface {
    Action()
    }

    type Person struct {
    Name string
    }

    type Dog struct {
    Name string
    }

    func (p *Person)Action() {
    fmt.Println("person action")
    }

    func (p *Dog)Action() {
    fmt.Println("dog action")
    }

    func main() {
    var dao bytes.Buffer

    encoder := gob.NewEncoder(&dao)
    decoder := gob.NewDecoder(&dao)

    var action Actioner
    action = &Person{"chen"}
    err := encoder.Encode(&action)
    if err != nil{
    panic(err)
    }
    action = &Dog{"jok"}
    err = encoder.Encode(&action)
    if err != nil{
    panic(err)
    }

    err = decoder.Decode(&action)
    if err != nil{
    panic(err)
    }
    fmt.Println(action)
    action.Action()

    err = decoder.Decode(&action)
    if err != nil{
    panic(err)
    }

    fmt.Println(action)
    action.Action()
    }
    我们也可以将*bytes.Buffer换成*os.File,将编码后的对象写入磁盘存储

    性能测试

    下面进行一下简单的性能测试,测试一下gob和json的编解码性能。

    gob:

    package main

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

    type Person struct {
    Name string
    Age int
    Action Run
    }

    type Run struct {
    Speed int
    }
    var dao bytes.Buffer

    var encoder = gob.NewEncoder(&dao)
    var decoder = gob.NewDecoder(&dao)

    func Gob() {

    p := Person{Name:"chen",Age:18,Action:Run{80}}

    err := encoder.Encode(&p)
    if err != nil{
    panic(err)
    }

    //fmt.Println(dao.String())

    var d Person
    err = decoder.Decode(&d)
    if err != nil{
    panic(err)
    }

    //fmt.Println(d)
    }

    func main() {
    now := time.Now()
    start := now.UnixNano()
    for i := 0; i < 10000; i++ {
    Gob()
    }
    now2 := time.Now()
    end := now2.UnixNano()
    fmt.Println(end - start) //25016400
    }
    gob编解码循环10000次所需时间为25016400纳秒

    json:

    package main

    import (
    "encoding/json"
    "fmt"
    "time"
    )

    type Person struct {
    Name string `json:"name"`
    Age int `json:"age"`
    Action Run `json:"action"`
    }

    type Run struct {
    Speed int `json:"speed"`
    }

    func Json() {
    p := Person{Name:"chen",Age:18,Action:Run{80}}

    data,err := json.Marshal(p)
    if err != nil{
    panic(err)
    }

    //fmt.Println(string(data))

    var d Person
    err = json.Unmarshal(data,&d)
    if err != nil{
    panic(err)
    }

    //fmt.Println(d)
    }

    func main() {
    now := time.Now()
    start := now.UnixNano()
    for i := 0; i < 10000; i++ {
    Json()
    }
    now2 := time.Now()
    end := now2.UnixNano()
    fmt.Println(end - start) //45037200
    }
    json编解码循环10000次所需时间为45037200纳秒

    总结:粗略的测试gob的性能大概是json的两倍左右

  • 相关阅读:
    Java学习之Math类理解
    Java学习之集合框架的迭代器--Iteratorjk及ListItertor接口
    Java学习关于随机数工具类--Random类
    集合框架学习之List接口
    Java学习关于集合框架的基础接口--Collection接口
    Java基础学习之数组基本属性和方法
    Java学习关于时间操作的应用类--Date类、Calendar类及其子类
    Java学习--异常处理及其应用类
    LR百分比模式
    lr函数之lr_eval_string()函数的使用学习
  • 原文地址:https://www.cnblogs.com/mafeng/p/10120088.html
Copyright © 2011-2022 走看看