![b96bf659bf4d37062e1c8b4952ac50f4.png](https://i-blog.csdnimg.cn/blog_migrate/866b8992401d0e2663f7c3513f631975.jpeg)
导语:如果你正在寻找一种简单高效的go的对象序列化方案,嫌弃json太慢,太松散,嫌弃gob效率不高,只适用于go,pb用起来太麻烦的话,这篇文章就可能是你需要的,公司内部使用go的团队越来越多,希望给大家带来便利
背景
数据的序列化具备广泛的使用场景,比如rpc调用中,请求和响应的传输,对象放入redis,文件等进行缓存。业界比较通行的,适用于go语言的序列化方案,比较有代表性的主要有: json、gob、pb等。json可读性好,但性能比较差,结构比较松散,描述接口不够精确。Gob由于只适用于go,而且实测下来性能也不是很理想。Pb速度比较快,跨语言,但是使用起来比较麻烦,需要先定义pb文件,然后生成代码。
本文介绍一种二进制序列化协议及其实现,readygo binnary(以下简称RGB),readygo 是我们即将开放的一个go的带服务调用全链路跟踪,负载均衡,和tnm监控结合等功能,零配置,业务代码零侵入的RPC框架。正是在开发readygo的过程中,看到需要一个序列化的方法,于是RGB诞生了
设计目标(已实现)
1、不需要写类似pb的中间文件,根据对象本身定义即可完成
2、性能要高,采用二进制打包,加快传输,解析速度
3、支持所有基础数据类型,以及struct组合以及数组,map等,及其嵌套
4、语言无关,可支持跨语言
5、支持向前向后兼容,即数据增加新的字段后,老的程序能够正常解析,老程序发出的老版本的数据,新版本程序能够正常解析
![dedbf130cd6ae948fcf25170f47635ab.png](https://i-blog.csdnimg.cn/blog_migrate/f33f6b14ba3f95a5e806f97f27799daa.jpeg)
实测性能
详细展开之前,先看一下benchmark的结果,在选定的测试用例下,RGB速度大概是json的5倍,是Gob的22倍。
go test -benchmem -run=^$ readygo/tk -bench ^*Encode$goos: linuxgoarch: amd64pkg: readygo/tkBenchmarkJsonEncode-8 200000 6744 ns/op 416 B/op 13 allocs/opBenchmarkGobEncode-8 50000 35886 ns/op 9279 B/op 247 allocs/opBenchmarkRGBEncode-8 1000000 1628 ns/op 240 B/op 7 allocs/opPASSok readygo/tk 5.229s
使用示例
接口上类似json包的使用方法,示例如下
data := your_datadataUnpack := pointer to your dataenc := NewRGBEncoder()bt := enc.Marshal(data)dec := NewRGBDecoder(bt)dec.UnMarshal(dataUnpack)
实现详解
Talk is cheap,show me your code,所以简单说一下思路,方便阅读代码,详细以代码来说话
1、 基本数值类型(整数,小数,bool),直接存入byte buffer
2、 字符串string,前面先存入长度,后面存入内容
3、 结构体struct,起始存入长度,依次对每个成员递归
4、 列表类型,起始存入元素个数,对每个元素递归
5、 MAP类型,起始存入元素个数,对每个元素递归
详细参考代码
![959a64e120fcaffe0199618fdc246e01.png](https://i-blog.csdnimg.cn/blog_migrate/bf344e98e95823588ccef4f2630798e2.jpeg)
链接:https://share.weiyun.com/5srsfqp
![0f8154a6da067407478ad58478c0e1b8.png](https://i-blog.csdnimg.cn/blog_migrate/bfea64ef8672b8311914741b309278b8.jpeg)
链接:https://share.weiyun.com/5XKoS5l
TODO
1、 数据长度类型,元素个数之类的,可以采用varint进一步压缩,暂时考虑到简单性未做此处理
2、C/C++版本的请参阅我历史文章,很多年前已有实现
3、根据go直接转生成其他语言(不确定是否要做,这种场景就请用pb吧)