Golang 序列化方式及对比
Golang 序列化方式及对比 - fengfengdiandia的专栏 - CSDN博客 https://blog.csdn.net/fengfengdiandia/article/details/79986237
Golang 序列化的方式:
- Binary
- Gob
- JSON
- Protobuf
一. Binary
// OK
type Message struct {
Id uint64
Size uint64
}
// Wrong
/*type Message struct {
Id int
Size int
Data string
}*/
func BinaryRW() {
m1 := Message{1, 1024}
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.LittleEndian, m1); err != nil {
log.Fatal("binary write error:", err)
}
var m2 Message
if err := binary.Read(buf, binary.LittleEndian, &m2); err != nil {
log.Fatal("binary read error:", err)
}
}
注意: 如果字段中有不确定大小的类型,如 int,slice,string 等,则会报错。
binary write error:binary.Write: invalid type main.Message
下面是binary.Write的函数说明:
// Data must be a fixed-size value or a slice of fixed-size values.
func Write(w io.Writer, order ByteOrder, data interface{}) error {
解决办法:
- int 换成 int32 等固定大小的类型
- slice 换成类似 [8]byte 这种固定大小
- 选择其他序列化方式
二. Gob
针对 binary 不能直接使用 string 和 slice 问题,可以使用 gob。
type Message2 struct {
Id uint64
Size uint64
Data string
}
func GobEncodeDecode() {
m1 := Message2{2, 1024, "gob"}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
if err := enc.Encode(m1); err != nil {
log.Fatal("encode error:", err)
}
var m2 Message2
if err := dec.Decode(&m2); err != nil {
log.Fatal("decode error:", err)
}
}
三. JSON
还可以使用 json 传递数据
type Message2 struct {
Id uint64 `json:"id"`
Size uint64 `json:"size"`
Data string `json:"data"`
}
func JsonEncodeDecode() {
m1 := Message2{3, 1024, "json"}
var buf []byte
var err error
if buf, err = json.Marshal(m1); err != nil {
log.Fatal("json marshal error:", err)
}
var m2 Message2
if err = json.Unmarshal(buf, &m2); err != nil {
log.Fatal("json unmarshal error:", err)
}
}
四. Protobuf
当然,还可以使用 protobuf 来序列化.
test.proto
syntax = "proto2";
package example;
message Message {
required uint64 id = 1;
required uint64 size = 2;
required string data = 3;
}
func ProtoEncodeDecode() {
m1 := &example.Message{
Id: proto.Uint64(4),
Size: proto.Uint64(1024),
Data: proto.String("proto"),
}
buf, err := proto.Marshal(m1)
if err != nil {
log.Fatal("proto marshal error:", err)
}
var m2 example.Message
if err = proto.Unmarshal(buf, &m2); err != nil {
log.Fatal("proto unmarshal error:", err)
}
fmt.Println(m2.GetId(), m2.GetSize(), m2.GetData())
}
五. BenchMark 对比
现在来对比下这几种序列化方式的性能。
目录结构:
$ tree serialize
serialize
├── serialize.go
├── serialize_test.go
└── example
├── test.pb.go
└── test.proto
serialize.go
package serialize
import (
"bytes"
"encoding/binary"
"encoding/gob"
"encoding/json"
"log"
"serialize/example"
"github.com/golang/protobuf/proto"
)
type Message struct {
Id uint64
Size uint64
}
type Message2 struct {
Id uint64 `json:"id"`
Size uint64 `json:"size"`
Data string `json:"data"`
}
func BinaryRW() {
m1 := Message{1, 1024}
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.LittleEndian, m1); err != nil {
log.Fatal("binary write error:", err)
}
var m2 Message
if err := binary.Read(buf, binary.LittleEndian, &m2); err != nil {
log.Fatal("binary read error:", err)
}
}
func GobEncodeDecode() {
m1 := Message2{2, 1024, "gob"}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
dec := gob.NewDecoder(&buf)
if err := enc.Encode(m1); err != nil {
log.Fatal("encode error:", err)
}
var m2 Message2
if err := dec.Decode(&m2); err != nil {
log.Fatal("decode error:", err)
}
}
func JsonEncodeDecode() {
m1 := Message2{3, 1024, "json"}
var buf []byte
var err error
if buf, err = json.Marshal(m1); err != nil {
log.Fatal("json marshal error:", err)
}
var m2 Message2
if err = json.Unmarshal(buf, &m2); err != nil {
log.Fatal("json unmarshal error:", err)
}
}
func ProtoEncodeDecode() {
m1 := &example.Message{
Id: proto.Uint64(4),
Size: proto.Uint64(1024),
Data: proto.String("proto"),
}
buf, err := proto.Marshal(m1)
if err != nil {
log.Fatal("proto marshal error:", err)
}
var m2 example.Message
if err = proto.Unmarshal(buf, &m2); err != nil {
log.Fatal("proto unmarshal error:", err)
}
}
serialize_test.go
package serialize
import (
"testing"
)
func BenchmarkBinaryRW(b *testing.B) {
for i := 0; i < b.N; i++ {
BinaryRW()
}
}
func BenchmarkGobEncodeDecode(b *testing.B) {
for i := 0; i < b.N; i++ {
GobEncodeDecode()
}
}
func BenchmarkJsonEncodeDecode(b *testing.B) {
for i := 0; i < b.N; i++ {
JsonEncodeDecode()
}
}
func BenchmarkProtoEncodeDecode(b *testing.B) {
for i := 0; i < b.N; i++ {
ProtoEncodeDecode()
}
}
BenchmarkBinaryRW-4 2000000 609 ns/op
BenchmarkGobEncodeDecode-4 100000 23689 ns/op
BenchmarkJsonEncodeDecode-4 1000000 1889 ns/op
BenchmarkProtoEncodeDecode-4 2000000 778 ns/op
PASS
ok serialize 8.722s
| 方式 | 优点 | 缺点 |
|---|---|---|
| binary | 性能高 | 不支持不确定大小类型 int、slice、string |
| gob | 支持多种类型 | 性能低 |
| json | 支持多种类型 | 性能低于 binary 和 protobuf |
| protobuf | 支持多种类型,性能高 | 需要单独存放结构,如果结构变动需要重新生成 .pb.go 文件 |
写在最后
注意: 网络传输上面类似数据时,记得要考虑粘包问题。
Golang 序列化方式及对比的更多相关文章
- .net 各种序列化方式效率对比
在服务与服务之间传输的是二进制数据,而在此之前有多种方法将数据内容进行序列化来减小数据传递大小,现针对于目前主流的几种序列化方式做了简单数据统计对比. 先做下简单介绍↓↓↓ 1.protobuf-ne ...
- springboot系列十一、redisTemplate和stringRedisTemplate对比、redisTemplate几种序列化方式比较
一.redisTemplate和stringRedisTemplate对比 RedisTemplate看这个类的名字后缀是Template,如果了解过Spring如何连接关系型数据库的,大概不会难猜出 ...
- [java]序列化框架性能对比(kryo、hessian、java、protostuff)
序列化框架性能对比(kryo.hessian.java.protostuff) 简介: 优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...
- python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)
一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...
- 深入浅出爬虫之道: Python、Golang与GraphQuery的对比
深入浅出爬虫之道: Python.Golang与GraphQuery的对比 本文将分别使用 Python ,Golang 以及 GraphQuery 来解析某网站的 素材详情页面 ,这个页面的特色是具 ...
- 【转】几种Java序列化方式的实现
0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生 ...
- Redis 序列化方式StringRedisSerializer、FastJsonRedisSerializer和KryoRedisSerializer
当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的.RedisTemplate默认使用的是JdkSerializat ...
- 序列化框架性能对比(kryo、hessian、java、protostuff)
简介: 优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Protostuff 速度快,基于protobuf 需静态编译 Protostuff- ...
- Android进程通信之一:两种序列化方式
2月下旬辞职了,去海南度假到现在,领略了一把三亚风情也算任性和 然而这样任性带来的后果就是..不行了我必须吐槽一句.. 没毕业的找工作就这么难嘛!投了57家一家面试机会都没有,好歹给个面试机会啊!!本 ...
随机推荐
- MongoDB管理
前几篇文章都是从开发和使用的角度了解了MongoDB的各个知识点,这篇文章将从MongoDB管理的角度入手,了解MongoDB管理所要了解的基本知识. 数据库命令 在前面几篇文章中,已经接触了一些数据 ...
- Explaining Delegates in C# - Part 6 (Asynchronous Callback - Way 3)
By now, I have shown the following usages of delegates... Callback and Multicast delegatesEventsOne ...
- /etc/issue
/etc/issue 与 /etc/motd 作用一致,都是用于显示欢迎信息,区别在于 /etc/issue 是在 login 提示符之前显示,而 /etc/motd 则在在用户成功登录系统之后显示 ...
- 使用 requests 维持会话
什么是 Cookie 和 Session: 简单来说,我们访问每一个互联网页面,都是通过 HTTP 协议进行的,而 HTTP 协议是一个无状态协议,所谓的无状态协议即无法维持会话之间的状态.比如,仅使 ...
- 流程控制与数组——Java疯狂讲义
顺序结构 if分支语句 if{} 可以有多个else if{} else{} 可以省略 switch分支语句 while循环 do while循环 for循环 嵌套循环 控制循环结构 理解数 ...
- nodeJs学习过程之认识nodejs
nodeJs只是听说过,没见过,没玩过.从新手开始,我想慢慢掌握它. 一.首先,我想知道nodeJs是什么? 摘自百度百科: Node.js是一套用来编写高性能网络服务器的JavaScript工具包, ...
- vue回到顶部的事件
其实只需要一句代码就好了: document.documentElement.scrollTop = document.body.scrollTop = ;
- YII2 model 字段验证提示 Unknown scenario: update
意思是 update 场景不存在,也就是 定义的 rules 中没有该规则: /** * @inheritdoc * 验证规则 */ public function rules() { return ...
- JS - 查找同辈中的对象
今天在使用parent().find(".a:first")的时候,发现查找结果非正常按照顺序来的.有点递归的感觉,从底层往上. 因为需要的是同级的对象,所以去查了一下jquery ...
- java基础---->Runtime类的使用(一)
这里面我们对java中的Runtime类做一个简单的了解介绍.若不常想到无常和死,虽有绝顶的聪明,照理说也和呆子一样. Runtimeo类的使用 一.得到系统内存的一些信息 @Test public ...