这是我参与「第五届⻘训营 」笔记创作活动的第7天。
这篇文章介绍一下项目中关于protobuf的使用。由于项目说明中给了接口的proto定义,于是可以利用protoc-gen-go工具来根据接口生成代码,可以统一接口定义实现。
protobuf 介绍
protobuf 即 Protocol Buffers,是一种轻便高效的结构化数据存储格式,与语言、平台无关,可扩展可序列化。protobuf 性能和效率大幅度优于 JSON、XML 等其他的结构化数据格式。protobuf 是以二进制方式存储的,占用空间小,但也带来了可读性差的缺点。protobuf 在通信协议和数据存储等领域应用广泛。
Protobuf 在 .proto 定义需要处理的结构化数据,可以通过 protoc 工具,将 .proto 文件转换为 C、C++、Golang、Java、Python 等多种语言的代码,兼容性好,易于使用。
安装
protoc
$ brew install protobuf
$ protoc --version
libprotoc x.x.x
当然也可以源码安装。
protoc-gen-go
我们需要在 Golang 中使用 protobuf,还需要安装 protoc-gen-go,这个工具用来将 .proto 文件转换为 Golang 代码。
go get -u github.com/golang/protobuf/protoc-gen-go
使用
以项目给定的proto文件为例子。
syntax = "proto2";
package douyin.core;
option go_package = "./core;core";
message User {
required int64 id = 1; // 用户id
required string name = 2; // 用户名称
optional int64 follow_count = 3; // 关注总数
optional int64 follower_count = 4; // 粉丝总数
required bool is_follow = 5; // true-已关注,false-未关注
optional string avatar = 6; //用户头像
optional string background_image = 7; //用户个人页顶部大图
optional string signature = 8; //个人简介
optional int64 total_favorited = 9; //获赞数量
optional int64 work_count = 10; //作品数量
optional int64 favorite_count = 11; //点赞数量
}
此时项目文件结构如下
.
├── go.mod
├── go.sum
├── main.go
└── pb
└──basic_api.proto
在pb目录使用命令
protoc --go_out=. *.proto
生成代码,为User的model代码,此代码可以用于序列化和反序列化传递。
.
├── go.mod
├── go.sum
├── main.go
└── pb
├── basic_api.proto
└── core
└── basic_api.pb.go
测试
在main.go中进行User的序列化与反序列化测试,
package main
import (
"dousheng/pb/core"
"log"
"google.golang.org/protobuf/proto"
)
func main() {
var id int64
test := &core.User{
Id: &id,
Name: new(string),
FollowCount: new(int64),
FollowerCount: new(int64),
IsFollow: new(bool),
Avatar: new(string),
BackgroundImage: new(string),
Signature: new(string),
TotalFavorited: new(int64),
WorkCount: new(int64),
FavoriteCount: new(int64),
}
//序列化
data, err := proto.Marshal(test)
if err != nil {
log.Fatal("proto encode error: ", err)
return
}
//反序列化
newTest := &core.User{}
err = proto.Unmarshal(data, newTest)
if err != nil {
log.Fatal("proto decode error: ", err)
return
}
if test.GetId() != newTest.GetId() {
log.Fatalf("data mismatch id %d != %d", test.GetId(), newTest.GetId())
return
} else {
log.Println("data matched!")
}
}
结果如下
2023/01/20 23:41:48 data matched!
结论
可以看到,使用工具可以大大提高代码效率,毕竟很多基础的代码不用自己写了,可以集中更多精力在业务流程之上。使用protobuf也比使用json传递数据效率更高,可以提高系统性能。
之后的项目中会将protobuf和grpc一起使用,使用proto文件生成可以用于rpc调用的代码,之后会写一篇文章说明。