当前位置: 首页 > 工具软件 > GOB > 使用案例 >

gob编解码

程鸿波
2023-12-01

要让数据对象能在网络上传输或存储,我们需要进行编码和解码。现在比较流行的编码方式有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的两倍左右

参考:https://golang.org/pkg/encoding/gob/

            https://www.cnblogs.com/yjf512/archive/2012/08/24/2653697.html

 类似资料: