9.4 Go 数据格式

1.1. msgpack格式

官方msgpack官网用一句话总结: It’s like JSON. but fast and small. 简单来讲,它的数据格式与json类似,但是在存储时对数字、多字节字符、数组等都做了很多优化,减少了无用的字符,二进制格式,也保证不用字符化带来额外的存储空间的增加。

msgpack使用示例代码

package main

import (
"fmt"
"github.com/vmihailenco/msgpack"
"io/ioutil"
"math/rand"
) type Person struct {
Name string
Age int
Sex string
} //写入json
func writeJson(filename string) (err error) {
var persons []*Person //切片,只能放入Person地址
//生成10个结构体对象
for i := 0; i < 100; i++ {
p := &Person{
Name: fmt.Sprintf("name%d", i),
Age: rand.Intn(100),
Sex: "Man",
}
//循环讲结构体放入切片
persons = append(persons, p)
}
//序列化切片
data, err := msgpack.Marshal(persons)
if err != nil {
fmt.Printf("=marshal failed, err:%v\n", err)
return
}
//写入序列化后的数据,到filename中
err = ioutil.WriteFile(filename, data, 0755)
if err != nil {
fmt.Printf("write file failed, err:%v\n", err)
return
} return
} //读取json数据,传入文件参数
func readJson(filename string) (err error) {
var persons []*Person
data, err := ioutil.ReadFile(filename)
if err != nil {
return
} err = msgpack.Unmarshal(data, &persons)
if err != nil {
return
} for _, v := range persons {
fmt.Printf("%#v\n", v)
}
return
} func main() {
filename := "./person.dat"
err := writeJson(filename)
if err != nil {
fmt.Printf("write json failed, err:%v\n", err)
return
} err = readJson(filename)
if err != nil {
fmt.Printf("read json failed, err:%v\n", err)
return
}
}

json代码

package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
) type Person struct {
Name string
Age int
Sex string
} //写入json
func writeJson(filename string) (err error) {
var persons []*Person //切片,只能放入Person地址
//生成10个结构体对象
for i := 0; i < 100; i++ {
p := &Person{
Name: fmt.Sprintf("name%d", i),
Age: rand.Intn(100),
Sex: "Man",
}
//循环讲结构体放入切片
persons = append(persons, p)
}
//序列化切片
data, err := json.Marshal(persons)
if err != nil {
fmt.Printf("=marshal failed, err:%v\n", err)
return
}
//写入序列化后的数据,到filename中
err = ioutil.WriteFile(filename, data, 0755)
if err != nil {
fmt.Printf("write file failed, err:%v\n", err)
return
} return
} //读取json数据,传入文件参数
func readJson(filename string) (err error) {
var persons []*Person
data, err := ioutil.ReadFile(filename)
if err != nil {
return
} err = json.Unmarshal(data, &persons)
if err != nil {
return
} for _, v := range persons {
fmt.Printf("%#v\n", v)
}
return
} func main() {
filename := "./person.txt"
err := writeJson(filename)
if err != nil {
fmt.Printf("write json failed, err:%v\n", err)
return
} err = readJson(filename)
if err != nil {
fmt.Printf("read json failed, err:%v\n", err)
return
}
}

Json包和msgpack包协议一样,区别:

API的不同
json.Marshal
json.Unmarshal msgpack.Marshal
msgpack.Unmarshal msgpack占用传输更快
yugoMBP:gobook yuchao$ ls -lh
total 32
-rw-r--r-- 1 yuchao staff 1.3K Mar 10 18:16 main.go
-rwxr-xr-x 1 yuchao staff 3.3K Mar 10 18:16 person.dat
-rwxr-xr-x 1 yuchao staff 3.8K Mar 10 18:16 person.txt

1.2. protobuf数据交换格式

什么是protobuf

Protobuf(Protocol Buffer)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

什么是protoc

protoc是protobuf文件(.proto)的编译器,可以借助这个工具把 .proto 文件转译成各种编程语言对应的源码,包含数据类型定义、调用接口等。

通过查看protoc的源码(参见github库)可以知道,protoc在设计上把protobuf和不同的语言解耦了,底层用c++来实现protobuf结构的存储,然后通过插件的形式来生成不同语言的源码。可以把protoc的编译过程分成简单的两个步骤(如上图所示):1)解析.proto文件,转译成protobuf的原生数据结构在内存中保存;2)把protobuf相关的数据结构传递给相应语言的编译插件,由插件负责根据接收到的protobuf原生结构渲染输出特定语言的模板。


为什么用protobuf

最近的项目中,一直使用Json做数据传输。Json用起来的确很方便。但相对于protobuf数据量更大些。做一个移动端应用,为用户省点流量还是很有必要的。正好也可以学习一下protobuf的使用

跟Json相比protobuf性能更高,更加规范

编解码速度快,数据体积小

使用统一的规范,不用再担心大小写不同导致解析失败等蛋疼的问题了

但也失去了一些便利性

改动协议字段,需要重新生成文件。

数据没有可读性

介绍:

Google推出的数据交换格式

二进制

代码自动生成

宇宙最快格式

开发流程:
IDL编写
生成指定语言的代码
序列化-反序列化

1.3. 安装protoc

下载地址:

https://github.com/protocolbuffers/protobuf/releases

osx:https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-osx-x86_64.zip
windows 64位:https://github.com/protocolbuffers/protobuf/releases/download/v3.7.0/protoc-3.7.0-win64.zip

下载完毕后,配置protoc的PATH环境变量

PATH="添加protoc的环境变量"

1.4. 下载golang代码插件protoc-gen-go

安装golang代码插件,如果下载出现问题,删除文件夹github.com/golang/protobuf重新下载
go get -u github.com/golang/protobuf/protoc-gen-go
go install github.com/golang/protobuf/protoc-gen-go

添加protoc-gen-go命令到PATH变量中

进入protobuf的文件夹,创建address文件夹
mkdir address
//生成go文件
protoc --go_out=./address/ ./person.proto

应用实例

package main

import (
"fmt"
"io/ioutil" "./address"
"github.com/golang/protobuf/proto"
) func writeProto(filename string) (err error) {
var contactBook address.ContactBook
for i := 0; i < 64; i++ {
p := &address.Person{
Id: int32(i),
Name: fmt.Sprintf("武%d", i),
} phone := &address.Phone{
Type: address.PhoneType_HOME,
Number: "15210858000",
} p.Phones = append(p.Phones, phone)
contactBook.Persons = append(contactBook.Persons, p)
}
//序列化protobuf数据
data, err := proto.Marshal(&contactBook)
if err != nil {
fmt.Printf("marshal proto buf failed, err:%v\n", err)
return
} err = ioutil.WriteFile(filename, data, 0755)
if err != nil {
fmt.Printf("write file failed, err:%v\n", err)
return
}
return
} func readProto(filename string) (err error) {
var contactBook address.ContactBook
data, err := ioutil.ReadFile(filename)
if err != nil {
return
}
err = proto.Unmarshal(data, &contactBook)
if err != nil {
return
} fmt.Printf("proto:%#v\n", contactBook)
return
} func main() {
filename := "./contactbook.dat"
err := writeProto(filename)
if err != nil {
fmt.Printf("write proto failed, err:%v\n", err)
return
}
err = readProto(filename)
if err != nil {
fmt.Printf("read proto failed, err:%v\n", err)
return
}
}

9.4 Go 数据格式的更多相关文章

  1. libsvm的数据格式及制作

    1.libsvm数据格式 libsvm使用的训练数据和检验数据文件格式如下: [label] [index1]:[value1] [index2]:[value2] … [label] [index1 ...

  2. Data组件的JSON数据格式

    {     // "@type" - 类型标识,"table"表明这个JSON是一个table结构的数据     "@type" : &qu ...

  3. 【原创】开源Math.NET基础数学类库使用(04)C#解析Matrix Marke数据格式

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  4. 【原创】开源Math.NET基础数学类库使用(05)C#解析Delimited Formats数据格式

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  5. 黄聪:phpexcel中文教程-设置表格字体颜色背景样式、数据格式、对齐方式、添加图片、批注、文字块、合并拆分单元格、单元格密码保护

    首先到phpexcel官网上下载最新的phpexcel类,下周解压缩一个classes文件夹,里面包含了PHPExcel.php和PHPExcel的文件夹,这个类文件和文件夹是我们需要的,把class ...

  6. XML和JSON数据格式对比

    概念 XML 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语 ...

  7. VS快速生成JSON数据格式对应的实体

          有固定好的Json数据格式,你还在手动敲对应的实体吗?有点low了!步入正题,这是一个json字符串,先去验证JSON数据格式(http://www.bejson.com/)如下: { & ...

  8. 数据格式json讲解

    JSON 在使用名称/值对或XML时,实际上是使用javascript从应用程序中取得数据并将数据转换成另一种数据格式.javascript不仅作为格式化语言使用,还可以使用javascript语言中 ...

  9. treeGrid树形数据表格的json数据格式说明

    在使用easyUI 的treeGrid的时候,很多时候我们从数据库取出来的数据treeGrid却不能读取显示成一个树:如下 { menuCode: "a00", menuName: ...

  10. jQuery EasyUI:根据数据库内容生成适合于easyui-tree的JSON数据格式

    1,jQuery EasyUI中easyui-tree特定的JSON数据格式 [ {"id":1,"text":"某公司","ch ...

随机推荐

  1. php 超全局变量(整理)

    来源:https://www.cnblogs.com/wsybky/p/8745286.html 一.$GLOBALS 在GLOBALS数组中,每一个变量为一个元素,键名对于变量名,值对于变量的内. ...

  2. 关于用C-free进行C语言编程在电脑中生成的.exe和.o文件

    在使用C-free进行C语言编程时,程序运行后会自动在电脑文件中生成以.exe和.o为后缀名的文件: 1,生成的.exe文件为系统自动打包完成的应用程序,该程序可直接在其他无C-free环境的电脑上运 ...

  3. Linux指令面试题01-进程查看与终止

    查看某一进程是否运行:ps -ef|grep 程序名 终止程序: kill pid 转载于:https://www.cnblogs.com/feihujiushiwo/p/10896636.html

  4. HDU 4009 Transfer water(最小树形图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...

  5. Aurora: 来自 Amazon 的高性能的企业级关系数据库,兼容 MySQL

    近日,在美国召开的AWS re:Invent云计算大会上,Amazon高级副总裁安迪·杰西发布了企业级关系数据库Aurora.Aurora是一个面向Amazon RDS(关系数据库服务).兼容MySQ ...

  6. bfs—迷宫问题—poj3984

    迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20591   Accepted: 12050 http://poj ...

  7. 疯子的算法总结10--最小生成树Kruscal

    按照权值排序可得,就有如下顺序: 1. 1-2 1 2. 1-4 2 3. 1-5 2 4. 2-5 3 5. 2-3 4 6. 4-5 4 每次选取最小边泉,判断是否同属一个集合,如果不属于同一集合 ...

  8. IDEA 打可执行jar包(maven项目)

    1. Ctrl+Shift+Alt+S  打开 Project Structure  2.选择要执行的文件,  依次选择 项目, 方法所在文件(必须有main方法), 保存 3.如果之前路径下曾经打过 ...

  9. 洛谷p1149

    一道很有意思的题目嘞. 这道题目看起来,用搜索似乎无疑了. 我想了这样一个办法(看了很多博客似乎都没用这种方法),可能是觉得太麻烦了吧: 1.我们先把0到9的数字排列,找出排列消耗火柴等于0的序列.这 ...

  10. B. Math Show 暴力 C - Four Segments

    B. Math Show 这个题目直接暴力,还是有点难想,我没有想出来,有点思维. #include <cstdio> #include <cstdlib> #include ...