文章目录
- Go 语言使用Protobuf 进行序列化详解
- 1. Protobuf是什么?
- 2. 安装Protobuf 及 Go 依赖
- 3. 编写.proto 文件
- 4. 实现序列化和反序列化
Go 语言使用Protobuf 进行序列化详解
1. Protobuf是什么?
以下是 Protobuf 官方中文文档的概述:
Protobuf(Protocol Buffers) 是一种语言中立、平台中立的可扩展机制,用于序列化结构化数据。
它类似于 JSON,但更小、更快,并且生成本机语言绑定。您只需定义一次数据结构,然后可以使用特殊生成的源代码轻松地将结构化数据读写到各种数据流中,并使用各种语言。
Protocol buffers 是定义语言(在 .proto 文件中创建)、proto 编译器生成的用于与数据交互的代码、特定于语言的运行时库、写入文件(或通过网络连接发送)的数据的序列化格式以及序列化数据的组合。
相比较传统的传输协议, 其以紧凑的二进制格式进行传输, 对比 json
,xml
等文本格式能显著减少数据体积, 对比文本格式通常小3-10倍
, 降低网络传输开销。
尤其是在序列化方面,得益于二进制数据无需文本解析, 处理速度更快,适合高性能场景。
2. 安装Protobuf 及 Go 依赖
使用 Protobuf
需要 Protobuf
编译器, 安装方法如下:
windows下载链接
在环境变量中加入Protobuf
bin 目录
Linux下载方法:
wget https://github.com/protocolbuffers/protobuf/releases/download/v30.0/protoc-30.0-linux-x86_64.zip
unzip protoc-30.0-linux-x86_64.zip -d /usr/local/
下载完成后输入
protoc --version
libprotoc 30.0 # 出现此行表示安装成功
安装 go protobuf
插件
go get -u google.golang.org/grpc
3. 编写.proto 文件
syntax = "proto3"; // 声明 protobuf 编译器版本
package Marshal; // 声明包
option go_package = "./Marshal"; // 声明生成 .pd.go 文件的路径 此处表示在当前目录中的 Marshal 目录中
// 声明一个消息类型
// 字段使用键值对的方式定义, 以 类型 字段名 唯一编号进行定义, 该编号用来在二进制格式消息中识别字段
message User{
int64 id = 1;
string name = 2;
string sex = 3;
float money = 4;
bool is_vip = 5;
repeated string tags = 6; // 数组类型
map<string, string> info = 7; // map类型
message Phone{ // 嵌套类型
string num1 = 1;
string num2 = 2;
}
Phone phone = 8; // 嵌套类型需声明为一个字段才能使用
}
4. 实现序列化和反序列化
使用 protobuf
编译器根据 .proto
文件生成对应的 .pb.go
文件
protoc --go_out=. --go-grpc_out=. protoFileName.proto
实现序列化和反序列化
import (
pd "Marshal/protobuf/Marshal" // 导入生成的 .pb.go 文件
f "fmt"
"google.golang.org/protobuf/proto" // 导入 proto 包
)
func main() {
// 定义 生成消息对应的结构体对象
user1 := &pd.User{
Id: 1001,
Name: "Tom",
Sex: "man",
Money: 100,
IsVip: false,
Tags: []string{"football", "games", "music"},
Info: map[string]string{"age": "18", "passwd": "000000"},
Phone: &pd.User_Phone{
Num1: "10086",
Num2: "10000",
},
}
user2 := pd.User{}
// 使用 proto 包中的 Marshal 方法对 user1 进行序列化
data, err := proto.Marshal(user1)
if err != nil {
f.Println(err)
}
f.Printf("二进制数据大小:%d bytes\n", len(data))
// 使用 proto 包中的 UnMarshal 方法对 user2 进行反序列化, 将数据反序列化进 user2
err = proto.Unmarshal(data, &user2)
if err != nil {
f.Println(err)
}
f.Println(user2)
}