2025年2月24日 星期一 甲辰(龙)年 腊月廿四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 网络通信

用protobuf代替json格式进行高效安全的数据通讯

时间:02-28来源:作者:点击数:24

protobuf 简介

protobuf 全称: Protocol Buffers, 是Google公司开发的一种数据类型和结构描述语言。是一种数据传输格式,网络数据传输数据,可用 json,也可用 protobuf

protobuf 很适合做数据存储或 RPC 数据交换格式,它序列化出来的数据量少再加上以 K-V 的方式来存储数据,对消息的版本兼容性非常强,可用于通讯协议、数据存储等领域的 语言无关、平台无关、可扩展的序列化结构数据格式

开发者可以通过Protobuf附带的工具,生成代码并实现将结构化数据序列化的功能。

安装 protoc 命令工具

protoc 命令,用来把后缀为 .proto 的文件(文件为不同编程语言通用的protobuf数据格式定义文件),编译成特定语言(C++, C#, Dart, Go, Java, Kotlin, Python, Objective-C, PHP, Ruby)的源文件(如.c, .go, .php, .py)。使得特定的编程语言可以直接调用,以解码或编码 protobuf 数据格式.

下载 protoc 命令工具 https://github.com/protocolbuffers/protobuf/releases

复制可执行文件到 环境变量目录. 如 $GOPATH/bin 目录

安装 protoc-gen-go 插件

前面提到,我们可以用 protoc 命令来编译 .proto 文件为特定语言的源文件。

为了支持编译为 go语言,需要安装 protoc-gen-go 插件.

使用 go install 命令下载 protoc-gen-go 插件:

  • go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

如此,在 $GOPATH/bin 下可见 protoc-gen-go.exe(linux) 或 protoc-gen-go.exe(windows) 文件.

后面执行 protoc 命令会自动调用 protoc-gen-go 插件

proto 文件介绍

字段规则
  • message User {
  • string username = 1;
  • int32 age = 2;
  • optional string password = 3;
  • repeated string address = 4;
  • }
  • required:消息体中必填字段,不设置会导致编解码异常
  • optional: 消息体中可选字段
  • repeated: 消息体中可重复字段,重复的值的顺序会被保留.在go中重复的会被定义为切片。
字段映射
proto Go Python C++
double float64 float double
float float32 float float
bytes []byte str string
string string str/unicode string

proto3 数据类型

默认值

protobuf3 删除了 protobuf2 中用来设置默认值的 default 关键字,取而代之的是protobuf3为各类型定义的默认值,也就是约定的默认值,如下表所示:

  • bool false
  • 整型 0
  • string 空字符串 “”
  • 枚举 第一个枚举元素的值,因为Protobuf3强制要求第一个枚举元素的值必须是0,所以枚举的默认值就是0
  • message 不是null,而是DEFAULT_INSTANCE
标识号

在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0,2^29-1]范围内的一个整数。

  • message Person {
  • string name = 1; // (位置1)
  • int32 id = 2;
  • optional string email = 3;
  • repeated string phones = 4; // (位置4)
  • }
嵌套消息
  • message PersonInfo {
  • message Person {
  • string name = 1;
  • int32 height = 2;
  • repeated int32 weight = 3;
  • }
  • repeated Person info = 1;
  • }
  • message PersonMessage {
  • PersonInfo.Person info = 1;
  • }

protobuf数据格式的编码和解码

创建测试项目

创建目录 testProto, 进入该目录,使用命令 go mod init testProto 初始化测试项目

编辑.proto源文件

在测试项目中,创建 protos 目录,在其中创建 .proto文件

vim user.proto:

  • // 指定的当前proto语法的版本,有2和3
  • syntax = "proto3";
  • //option go_package = "path;name"; ath 表示生成的go文件的存放地址,会自动生成目录的
  • // name 表示生成的go文件所属的包名
  • option go_package="../service";
  • // 指定等会文件生成出来的package
  • package service;
  • message User {
  • string username = 1;
  • int32 age = 2;
  • }
使用 protoc 命令生成go源码文件

在测试项目中,创建 service 目录,并执行命令生成go版本的protoc源码文件

  • # 编译user.proto之后输出到service文件夹
  • protoc --go_out=service protos/user.proto

以上命令在 service目录 生成 user.pb.go 文件

测试

测试项目中,编写 main.go文件,如下所示:

  • package main
  • import (
  • "fmt"
  • "google.golang.org/protobuf/proto"
  • "testProto/service"
  • )
  • func main() {
  • user := &service.User{
  • Username: "mszlu",
  • Age: 20,
  • }
  • //转换为protobuf
  • marshal, err := proto.Marshal(user)
  • if err != nil {
  • panic(err)
  • }
  • newUser := &service.User{}
  • err = proto.Unmarshal(marshal, newUser)
  • if err != nil {
  • panic(err)
  • }
  • fmt.Println(newUser.String())
  • }

运行命令:

  • # 解决包依赖
  • go mod tidy
  • # 运行
  • go run .
  • # 输出
  • username:"mszlu" age:20

测试项目结构如下:

  • ├── go.mod
  • ├── go.sum
  • ├── main.go
  • ├── protos
  • │ └── user.proto
  • └── service
  • └── user.pb.go

gRPC官方文档 https://grpc.io/docs/languages/go/quickstart/

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门