poroto3 坑 枚举_Protocol Buffer语法解析(proto3)

本文介绍了Protocol Buffer作为数据传输协议的优势和劣势,并对比了它与JSON的区别。详细解析了proto3的语法,包括message、enum、map等结构的使用,并给出了基础类型、字段修饰符和字段编号的规定。此外,还讨论了字段扩充的兼容性原则以及如何生成对应语言的源文件。
摘要由CSDN通过智能技术生成

背景

Protocol Buffer是google自定义的数据传输协议,目前已经被广泛用于服务端和客户端间的数据传输,清晰理解Protocol Buffer的使用以及语法就显得很重要,本文对Protocol Buffer语法分析是基于proto3.

传输协议对比

目前使用最广泛的数据传输协议为JSON,JSON是一种轻量级的数据交换格式而且层次和结构比较简单和清晰,这里主要对比一下Protocol Buffer和JSON的对比,给出优势和劣势:

优势

传输数据更小

序列化和反序列化更快

由于传输的过程中使用的是二进制,没有结构描述文件,无法解析内容,安全性更高

劣势

由于传输过程使用的是二进制,自解释性较差,需要原有的结构描述文件才能解析

实际数据对比

序列化速度:比JSON快20-100倍

数据大小:序列化后体积小3倍

使用流程

Protocol Buffer的使用流程总体可以分为三步,如下图所示:

根据业务创建并定义proto文件

使用Google Protocol Buffer 提供的工具生成对应语言的源文件

将源文件拷贝到工程中,使用Protocol Buffer提供的库序列化或反序列化数据

语法解析

在使用Protocol Buffer之前需要清楚理解其语法定义,本文对Protocol Buffer的语法解析是基于proto3版本

简单示例

首先创建一个.proto文件,并且在文件中声明如下内容:

syntax = "proto3";

message SearchRequest {

string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

}

复制代码

其中第一行标明当前proto使用的版本为proto3,后面定义了一个结构体SearchRequest,结构体中共3个属性。

字段

在整个proto文件中分为基本类型和结构类型,其中结构类型主要为:

message

enum

map

下面分别介绍一下不同结构的作用及规定:

message

message声明

message表示一个结构,类似于java中类,一个proto文件中可以声明多个message结构:

message SearchRequest {

string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

}

message SearchResponse {

...

}

复制代码

message引用

message可以引用不同proto文件中的message,只要在proto文件中的最上面声明import即可,如下所示:

import "myproject/other_protos.proto";

复制代码

message继承

meesage 可以使用extend来继承另外一个message,并且使用其中的属性,这里注意一下由于每个message中需要对属性进行编号,在继承的时候需要注意编号,防止重复使用

enum

enum使用

enum使用很简单,直接在message中声明enum结构体并且将属性声明为对应的enum即可:

message SearchRequest {

string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

enum Corpus {

UNIVERSAL = 0;

WEB = 1;

IMAGES = 2;

LOCAL = 3;

NEWS = 4;

PRODUCTS = 5;

VIDEO = 6;

}

Corpus corpus = 4;

}

复制代码

上面代码中Corpus就是一个enum

enum规定

在proto3中,enum第一个值必须为0,主要是为了和基础类型的默认值保持一致

map

map是proto3新加的,使用也很简单:

map map_field = N;

复制代码

在proto2中可以使用repeated和message结构自定义map,如下所示

message Person {

string key = 1;

string value = 2;

}

repeated Person person = 4;

复制代码

基础类型

proto中基础类型有很多,下面给出不同的基础类型对应的java中的类型,及其特点:

proto 类型

java类型

备注

double

double

float

float

int32

int

可变长度编码,如果有负值,可以使用sint32修饰

int64

long

可变长度编码,如果有负值,可以使用sint64修饰

uint32

int

可变长度编码

uint64

int

可变长度编码

sint32

int

可变长度编码,用来表示负值时效率比int32更高

sint64

long

可变长度编码,用来表示负值时效率比int64更高

fixed32

int

4个字节,当数值>2^28时效率比uint32高

fixed64

long

8个字节,当数值>2^56时效率比uint64高

sfixed32

int

4个字节

fixed64

long

8个字节

bool

boolean

string

String

UTF-8 encoded or 7-bit ASCII text, 长度不能超过2^32

bytes

ByteString

长度不超过2^32,任意顺序的字节数据

其中部分基本类型修饰符长度不确定,主要采用了可变长度编码,这也是为什么Prorocol Buffer序列化后的数据字节更少,这个后面原理篇会介绍。

默认值

基础类型的默认值如下:

string:空串

bytes:空字节

bool:false

数字类型:0

enum:默认值是第一个元素,且值必须为0

字段修饰符

singular:一个格式良好的消息应该有0个或者1个这种字段(但是不能超过1个)

repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次),重复的值的顺序会被保留,类似于java中的list

在proto3中,repeated的标量域默认情况下使用packed,也就是可变长度编码

字段编号

先看下一个简单的proto文件:

message SearchRequest {

string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

enum Corpus {

UNIVERSAL = 0;

WEB = 1;

IMAGES = 2;

LOCAL = 3;

NEWS = 4;

PRODUCTS = 5;

VIDEO = 6;

}

Corpus corpus = 4;

}

复制代码

message SearchRequest 中的所有字段都声明了字段编号,这里需要注意:

字段编号从1开始,不可重复定义

字段编号1-15尽量保持经常访问的字段使用,因为1-15编号在传输的过程中只占用1个字节

字段扩充

日常开发过程中,由于需求的变更,往往需要增加字段,这就涉及到字段的扩充,字段扩充需要达到一个目的:兼容

所以Protocol Buffer在字段扩充中定义了如下规则:

不要修改已经存在的字段标号

不用的字段,可以删除,但是编号一定不可以再次使用,建议将字段标为废弃,如加前缀:"OBSOLETE_"

只要记住上述规则,就能完成字段扩充且老版本也能兼容

生成对应语言文件

当proto文件编写后,就需要生成对应语言的源文件,生成操作如下:

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR --go_out=DST_DIR --ruby_out=DST_DIR --objc_out=DST_DIR --csharp_out=DST_DIR path/to/file.proto

复制代码IMPORT_PATH: proto文件中import的proto文件地址

XX_out:对应源文件输出地址

proto Path:源proto文件

原理简介

Protocol Buffer 更快更小的主要原因如下:

数据在序列化的时候不会传输字段名,只会传输字段标号,并且没有被设置值的字段是不会序列化和传输

采用可变长度编码,优化数据占用

总结

以上基于proto3讲述了Protocol Buffer的语法和使用流程,其中简单说明了Protocol Buffer为什么更快,更小,后面会详细介绍其原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值