分享
  1. 首页
  2. 文章

Go gob

JunChow520 · · 1939 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

为了让数据结构能够在网络中传输或保存到文件,它必须被编码后再解码。目前有多种可用的编码方式,比如JSON、XML、Google的Protocol Buffers等。

Gob(go binary)是Golang自己以二进制形式序列化和反序列化程序数据的格式,位于encoding/gob包中。类似于Python中的pickle和Java中Serialization

  • gob可用于传递远端程序调用(RPC)的参数和结果。
  • encoding/gob包实现了高效地序列化,特别是数据结构负责的,比如结构体、数字、切片。
  • encoding/gob用于管理gob流,gob流是指在编码器(发送器,encoder)和解码器(接收器,decoder)之间交换的字节流数据。

Gob和JSON一样由发送端使用Encoder对数据结构进行编码,当接收端接收到消息后使用Decoder将序列化的数据转换为本地变量。

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

Gob不是可外部定义且语言无关的编码方式,首选的是二进制格式,不像JSON或XML的文本格式。

Gob并不是一种不同于Go的语言,而是在编码和解码过程中用到Go的反射。

Gob可用于远程方法调用(RPC)参数和结果的传输,以及应用程序和机器之间的数据传输。

Gob只能用于纯Go环境中,例如两个使用Golang编写的服务之间的通信,以实现更加高效和优化。

Gob文件或流是完全自描述的,它里面包含的所有类型都有一个对应的描述,且都是可用Go语言解码,而无需了解文件的内容。

编码器 gob.NewEncoder

  • gob.NewEncoder接口参数w需实现io.Writer接口类型
func NewEncoder(w io.Writer) *Encoder {
 enc := new(Encoder)
 enc.w = []io.Writer{w}
 enc.sent = make(map[reflect.Type]typeId)
 enc.countState = enc.newEncoderState(new(encBuffer))
 return enc
}

编码 encoder.Encode

func (enc *Encoder) Encode(e interface{}) error {
 return enc.EncodeValue(reflect.ValueOf(e))
}

Gob序列化

Gob使用io.Writer接口会通过NewEncoder()函数创建Encoder对象,通过调用Encoder对象的Encode()方法实现编码操作。

创建结构体

type User struct{
 Id int
 Name string
}

编码序列化,结构体转换为bytes.Buffer,编码生成字节切片。

user := &User{Id:1, Name:"root"}
buf := new(bytes.Buffer)
encoder := gob.NewEncoder(buf)//创建编码器
err := encoder.Encode(user)//编码
if err!=nil {
 panic(err)
}
fmt.Printf("%x\n", buf.Bytes())
22ff81030101045573657201ff820001020102496401040001044e616d65010c0000000bff8201020104726f6f7400

封装编码生成字节切片

func encode(obj interface{}) (*bytes.Buffer, error){
 buf := new(bytes.Buffer)
 encoder := gob.NewEncoder(buf)
 err := encoder.Encode(obj)
 if err!=nil{
 return nil, err
 }
 return buf, err
}

编码生成字节缓存并保存到磁盘文件

//write gob序列化后写入文件
func write(data interface{}, filename string) (*bytes.Buffer, error){
 buf := new(bytes.Buffer)
 encoder := gob.NewEncoder(buf)
 err := encoder.Encode(data)
 if err!=nil{
 return nil, err
 }
 err = ioutil.WriteFile(filename, buf.Bytes(), 0600)
 if err!=nil{
 return nil, err
 }
 return buf, err
}

创建Gob文件

要使用Gob,首先需要通过NewEncoder()方法创建一个编码器,并向其提供一系列数据,然后再接收端通过调用NewDecoder()方法创建一个解码器,从数据流中恢复数据并将其填入本地变量中。

//write gob序列化后写入文件
func write(data interface{}, filename string) error{
 file,err := os.OpenFile(filename, os.O_RDWR | os.O_CREATE, 0777)
 if err!=nil{
 return err
 }
 defer file.Close()
 encoder := gob.NewEncoder(file)
 err = encoder.Encode(data)
 if err!=nil{
 return err
 }
 return nil
}
user := &User{Id:1, Name:"root"}
write(user, "user.gob")

解码器gob.NewDecoder

func NewDecoder(r io.Reader) *Decoder {
 dec := new(Decoder)
 // We use the ability to read bytes as a plausible surrogate for buffering.
 if _, ok := r.(io.ByteReader); !ok {
 r = bufio.NewReader(r)
 }
 dec.r = r
 dec.wireType = make(map[typeId]*wireType)
 dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
 dec.ignorerCache = make(map[typeId]**decEngine)
 dec.countBuf = make([]byte, 9) // counts may be uint64s (unlikely!), require 9 bytes
 return dec
}

反序列化decoder.Decode

func (dec *Decoder) Decode(e interface{}) error {
 if e == nil {
 return dec.DecodeValue(reflect.Value{})
 }
 value := reflect.ValueOf(e)
 // If e represents a value as opposed to a pointer, the answer won't
 // get back to the caller. Make sure it's a pointer.
 if value.Type().Kind() != reflect.Ptr {
 dec.err = errors.New("gob: attempt to decode into a non-pointer")
 return dec.err
 }
 return dec.DecodeValue(value)
}
//反序列化
reader := bytes.NewReader(bs.Bytes())
decoder := gob.NewDecoder(reader)
var u User
err = decoder.Decode(&u)
if err!=nil{
 panic(err)
}
fmt.Println(u) //{1 root}

读取Gob文件

file,err := os.Open("user.gob")
if err!=nil{
 panic(err)
}
decoder := gob.NewDecoder(file)
var user User
err = decoder.Decode(&user)
if err!=nil{
 panic(err)
}
fmt.Println(user)//{1 root}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:JunChow520

查看原文:Go gob

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1939 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏