前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go 语言网络编程系列(七)—— RPC 编程篇:默认编解码工具 Gob

Go 语言网络编程系列(七)—— RPC 编程篇:默认编解码工具 Gob

作者头像
学院君
发布2019-11-12 10:54:39
1.5K0
发布2019-11-12 10:54:39
举报
文章被收录于专栏:学院君的专栏

Gob 简介

Gob 是 Go 语言的一个序列化数据结构的编码解码工具,在 Go 标准库中内置了 encoding/gob 包以供使用。一个数据结构使用 Gob 进行序列化之后,能够用于网络传输,因此它的典型适用场景就是 RPC 编程,我们在上篇教程也提到了 net/rpc 包默认使用 encoding/gob 进行编解码,以 rpc.Client 为例,其初始化代码如下:

代码语言:javascript
复制
func NewClient(conn io.ReadWriteCloser) *Client {
  encBuf := bufio.NewWriter(conn)
  client := &gobClientCodec{conn, gob.NewDecoder(conn), gob.NewEncoder(encBuf), encBuf}
  return NewClientWithCodec(client)
}

发送端会在发送消息之前使用 gob.Encoder 对数据进行编码,接收端在收到消息后会通过 gob.Decoder 对数据进行解码,就像 PHP 中 json_encodejson_decode 所做的那样。

Gob 编解码规则

关于 Gob 编解码规则我们这里做一个简单的介绍,对 Gob 而言,发送方和接受方的数据结构并不需要完全一致,以官方示例为例:

上述 struct { A, B int } 结构编码的数据可以被后面 9 种结构类型接收解码,具体来说,接收数据结构只要满足与发送数据结构签名一致(与顺序无关,不能类型之间不能相互编解码,整型还要细分为有符号和无符号)、或者是发送数据类型的子集(但不能为空)或超集,即可正常接收并解码。

具体到不同的数据类型,规则如下:

  • structarrayslice 是可以被编码的,但是 functionchannel 是不能被编码的;
  • 整型分为有符号和无符号,无符号和有符号整型是不能互相编解码的;
  • 布尔类型是被当作 uint 来编码的,0false1true
  • 浮点型的值都是被当作 float64 类型的值来编码的,浮点型和整型也是不能相互编解码的;
  • 字符串类型(包含 string[]byte)是以无符号字节个数 + 每个字节编码的形式编解码的;
  • 数组类型(包含 slicearray)是按照无符号元素个数 + 每个数组元素编码的形式进行编解码的;
  • 字典类型(map)是按照无符号元素个数 + 键值对这样的形式进行编解码的;
  • 结构体类型(struct)是按照序列化的属性名 + 属性值来进行编解码的,其中属性值是其自己对应类型的 Gob 编码,如果有一个属性值为 0 或空,则这个属性直接被忽略,每个属性的序号是由编码时的顺序决定的,从 0 开始顺序递增。struct 在序列化前会以 -1 代表序列化的开始,以 0 代表序列化结束,即 struct 的序列化是按照 “-1 (0 属性1的名字 属性1的值) (1 属性2的名字 属性2的值) 0 ”来进行编码的。

最后,需要注意的是 struct 类型中的属性名都应该以大写字母开头,以便可以在包外被访问。

注:更多 Gob 编解码规则细节可以参考 encoding/gob 包文档:https://golang.google.cn/pkg/encoding/gob/ 和官方教程博客:https://blog.golang.org/gobs-of-data。

Gob 编解码使用示例

下面我们来看一个简单的 Gob 编解码实现示例:

代码语言:javascript
复制
package main

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

type P struct {
  X, Y, Z int
  Name    string
  Tags    []string
  Attr    map[string]string
}

type Q struct {
  X, Y *int32
  Name string
  Tags    []string
  Attr    map[string]string
}

func main() {
  var network bytes.Buffer
  enc := gob.NewEncoder(&network)  // 初始化编码器 gob.Encoder
  dec := gob.NewDecoder(&network)  // 初始化解码器 gob.Decoder
  // 数据编码(发送数据时)
  err := enc.Encode(P{3, 4, 5, "学院君", []string{"PHP", "Laravel", "Go"}, map[string]string{"webiste": "https://xueyuanjun.com"}})
  if err != nil {
    log.Fatal("encode error:", err)
  }
  // 数据解码(收到数据时)
  var q Q
  err = dec.Decode(&q)
  if err != nil {
    log.Fatal("decode error:", err)
  }
  fmt.Printf("%q: {%d,%d}, Tags: %v, Attr: %v\n", q.Name, *q.X, *q.Y, q.Tags, q.Attr)
}

其中涵盖了整型、字符串、切片、字典以及结构体类型的 Gob 编解码,执行上述代码,打印结果如下:

Gob 的优点与不足

与 JSON 或 XML 这种基于文本描述的数据交换格式不同,Gob 是二进制编码的数据流,因此性能和传输效率更高,并且 Gob 流是可以自解释的,从而具备了完整的表达能力。

但是,作为针对 Go 语言的数据结构编解码专用序列化工具,意味着 Gob 无法跨语言使用,只能仅局限于基于 Go 语言开发的 RPC 客户端与服务端进程间通信,然而,大多数时候,我们用 Go 语言编写的 RPC 服务端,可能更希望它是通用的,与语言无关的,无论是 PHP、Python、Java 或其他编程语言实现的 RPC 客户端,均可与之通信。面对这种情况,我们需要对 net/rpc 包底层的编解码工具进行自定义,改用跨语言的 JSON 或者 Protobuf 进行数据格式序列化,关于编解码工具的自定义,我们放到下一篇教程给大家详细介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客书房 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Gob 简介
  • Gob 编解码规则
  • Gob 编解码使用示例
  • Gob 的优点与不足
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档