二.ProtoBuf

简介

Google Protocol Buffer(简称ProtoBuf)是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议和数据存储等领域

其他数据格式比较

  1. xml :数据冗余,需要成对的闭合标签,在webservice中应用最广泛;
  2. json :使用了键值对的方式,压缩了一定的空间,同时也具有可读性。浏览器对其格式支持十分友好,有很多内建的函数支持;
  3. protobuf :二进制数据格式,需要编码和解码。数据本身不具备可读性,需要反序列化后得到真正的可读数据。适合高性能、对响应速度有要求的数据传输场景

优势

  1. 平台无关,语言无关;
  2. 二进制格式,序列化后体积相比于json和xml很小,适合网络传输;
  3. 使用protobuf的编译器,可以方便的生成在编程中使用的数据访问代码,提供了完整详细的操作api;
  4. 消息格式升级和兼容性良好;
  5. 序列化和反序列化速度很快,快于json的反应速度

安装

自己去装

编写.proto文件

定义一个消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
syntax = "proto3”;
package test;

message Param {
string key = 1; // 参数key
string value = 2; // 参数value
}

message request {
string url = 1; // 请求路由
string method = 2; // 请求方法
repeated Param params = 3; // 请求参数列表
}

message response {
int32 error = 1; // 返回错误
string message = 2; // 返回信息
}

编译

当使用protocol buffer编译器来运行.proto文件时,编译器将生成所选语言的代码,这些代码可以操作在.proto文件中定义的消息类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。

对C++来说,编译器会为生成一个.proto文件生成一个.h文件和.cc文件。.proto文件中的每一个消息都有一个对应的类。对go来说,一个.proto文件会生成一个.pb.go文件

1
2
3
4
5
➜  ls                                 
net.proto # 未编译前
➜ protoc -I ./ --go_out=./ *.proto # 使用protoc命令编译
➜ ls
net.pb.go net.proto # 编译后

使用

简单的写一个go程序调用上面编译生成的net.pb.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
"fmt"
"github.com/golang/protobuf/proto"
"go-proto/protos"
)

func main () {
param1 := &test.Param{
Key: "page_size",
Value: "1",
}
param2 := &test.Param{
Key: "page_num",
Value: "2",
}
req := &test.Request{
Url: "https://127.0.0.1/test",
Method: "GET",
Params: []*test.Param{param1, param2},
}

fmt.Println("request method before: ", req.GetMethod()) // 获取Method属性显示
req.Method = “POST” // 修改Method属性
req.Params[0].Value = "10"
fmt.Println("request method after: ", req.GetMethod())

data, err := proto.Marshal(req) // 编码
if err != nil {
fmt.Println("error: ", err)
}
fmt.Println("data: ", data)

newReq := &test.Request{}
proto.Unmarshal(data, newReq) // 解码
fmt.Println("request: ", newReq)
}

看看结果:

1
2
3
4
request method before:  GET
request method after: POST
data: [10 22 104 116 116 112 115 58 47 47 49 50 55 46 48 46 48 46 49 47 116 101 115 116 18 4 80 79 83 84 26 15 10 9 112 97 103 101 95 115 105 122 101 18 2 49 48 26 13 10 8 112 97 103 101 95 110 117 109 18 1 50]
request: url:"https://127.0.0.1/test" method:"POST" params:<key:"page_size" value:"10" > params:<key:"page_num" value:"2" >

上述调用的属性显示、属性修改、编码和解码方法皆定义在编译生成的net.pb.go文件中,文件中还有一些其它方法可供我们直接调用