protobuf文档翻译-安装,数据格式及编码规范
Install
Download protobuf: https://github.com/protocolbuffers/protobuf/releases
unzip protoc-3.8.0-linux-x86_64.zip
sudo cp -r include/* /usr/local/include/
sudo cp bin/protoc /usr/local/bin/
Download Go support for protobuf:
go get -u github.com/golang/protobuf/protoc-gen-go
Download faster and also more customizable Go support:
go get github.com/gogo/protobuf/protoc-gen-gofast
Proto2.0
每个proto文件中可以定义一组message。为了防止依赖关系等泛滥,一般只在一个proto文件中定义一组相关联的message。
定义一个message
message SomeMessage {
[required|optional] type fieldName = fieldNumber [default=10];
}
fieldNumber 从1开始。
注释
注释的语法和C++相同:
/* 这是一段注释 */
// 这也是一段注释
保留字段(Reserved Fields)
当一个字段被删除后,后续的用户可以重新使用这个字段数字或名字, 就导致proto迁移过程中可能造成一些潜藏的bug。可以通过保留声明他们,
将来如果有用户重用了这些字段,就会报错:
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
数据类型
proto | 注释 | Go | Python | C++ | Java |
---|---|---|---|---|---|
double | *float64 | float | double | double | |
float | *float32 | float | float | float | |
int32 | 编码长度是可变的,不能用于编码负数。如果要用于负数,应当使用sint32 | *int32 | int | int32 | int |
int64 | 类似int32,应当使用sint64编码负数 | *int64 | int/log | int64 | long |
uint32 | 变长编码 | *uint32 | int/long | uint32 | int |
uint64 | 变长编码 | *uint64 | int/long | uint64 | long |
sint32 | 变长编码 | *int32 | int | int32 | int |
sint64 | 变长编码 | *int64 | int/long | int64 | long |
fixed32 | 4字节,比uint32更适合编码超过2^28的数字 | *uint32 | int/long | uint32 | int |
fixed64 | 8字节,2^56 | *uint64 | int/long | uint64 | long |
sfixed32 | 4字节 | *int32 | int | int32 | int |
sfixed64 | 8字节 | *int64 | int/long | int64 | long |
bool | *bool | bool | bool | boolean | |
string | 必须是UTF-8编码或是7bit的ASCII | *string | unicode(Py2), str(Py3) | string | String |
bytes | 可以包含任意byte序列 | []byte | bytes | string | ByteString |
注意: 当说到更适合,或应当使用时,并不是说这个类型的表达范围不能够比得上另一种类型,而是其编码长度更有效率。
可选字段和默认值
一个message中可以设定一个字段为optional,当消息解码时发现该字段缺席,就会按照默认值(default)给定值,否则给定该类型的默认值(类似Go),枚举类型则会使用第一个枚举值。
形如:
optional int32 result_per_page = 3 [default=10];
枚举类型
枚举类型使用的是32位整形数,如果使用了负数,编码效率会变低。
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
}
枚举类型中默认第二个值是不能重复的,如果要有重复,那么就要指定允许别名:
enum State {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
保留枚举
如果你删除了枚举中的一个值,那么以后别人就可以重新用它们。可以这样保留这些字段:
enum Foo {
reserved 2, 15, 9 to 11, 40 to max;
reserved "FOO", "BAR";
}
导入定义
import "myproject/other_proto.proto"
import public "new.proto"
要想让protoc找到它们,需要通过 -I 或 --proto_path 来定义,一般是将项目根目录作为 --proto_path 参数。
类型嵌套
message SearchResponse {
message Result {
required string url = 1;
optional string title = 2;
repeated string snippets = 3;
}
repeated Result result = 1;
}
message SomeOtherMessage {
optional SearchResponse.Result result = 1; // 从外部引用一个嵌套类型
}
Proto3.0
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
- singular: 0或1个该字段
- repeated: 可以出现0到多个该字段
proto3中数字类型默认使用packed编码
类型更新
- 不要更改任何现有字段的field number
- 旧message的默认值应当保持不变
- 字段可以移除,在该field number不再使用的前提下
- int32/uint32/int64/uint64/bool 是兼容的,可以任意修改类型,但是可能会出现精度问题等
- sint32与sint64 兼容,但不与其它类型兼容
- string和bytes兼容,前提是它们都是有效的UTF-8编码
- 如果bytes包含了编码的message,嵌套message与bytes兼容
- fixed32 与 sfixed32/fixed64/sfixed64兼容
- enum与 int32/uint32/int64/uint64兼容
- 把单个字段放入一个新的oneof是安全且兼容的;把多个字段放入一个新的oneof 可能 是安全且兼容的,如果你确认没有代码同时设定这多个字段的前提下。 把任何字段放入一个现存的oneof是不安全兼容的。
未知字段
由于proto版本兼容问题,导致旧的废弃字段不能被使用,proto3开始时会直接丢弃它们,但从3.5开始将它们保留
任意类型
任意类型 Any 本质上就是序列化好的bytes类型, 使用该类型需要引入 google/protobuf/any.proto:
import "google/protobuf/any.proto";
message ErrorStatus {
string message = 1;
repeated google.protobuf.Any details = 2;
}
Oneof
如果message中有若干字段,一次最多只会设置其中的一个字段,那么就可以通过oneof来约定这种关系,类似于C语言的union:
message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}
oneof 的向后兼容
如果检查一个oneof的值返回 None/NOT_SET, oneof可能没有设置值,也可能是版本不同,但我们无法断定这件事。
Maps
map<key_type, value_type> map_field = N;
- map类型字段不可以是 repeated
- 遍历顺序/传输序列化顺序是不可知的
- 从map专程text格式时会对key做排序
- 从传输数据传入或合并时,如果map中的key存在重复,使用最后一个,从text格式处理map时,如果key重复会导致失败
- 如果只提供key但不提供值,那么序列化行为随语言而定
Map类型在传输时等价于:
message MapFieldEntry {
key_type key = 1;
value_type value = 2;
}
repeated MapFieldEntry map_field = N;
Packages
package foo.bar;
message Open { ... }
message Foo {
foo.bar.Open open = 1;
}
在Go中这会被当成包名
Services
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
Options
options不会修改数据定义,但是会影响一些语言生成的行为等等。
optimize_for
这是一个文件级选项,用于设定生成代码的优化方向。
optimize_for [SPEED|CODE_SIZE|LITE_RUNTIME]
SPEED: 默认值,优先生成高效编解码的代码
CODE_SIZE: 利用反射等语言特性生成体积小的代码,但操作可能会更慢
LITE_RUNTIME: 使用一个体积更小,也更少特性(如反射)的运行时来进行编解码
deprecacted
字段选项,用于暗示字段已弃用,新代码不应当再使用它。Java中会加入@Deprecated,其它语言暂不支持。
自定义选项
protobuf允许自定义选项,虽然大部分情况用不上: https://developers.google.com/protocol-buffers/docs/proto.html#extensions
JSON
protobuf 提供了JSON输出格式,部分类型可能与想象有所不同:
proto3 | JSON | JSON Example | Notes |
---|---|---|---|
enum | string | "FOO_BAR" | 默认使用枚举的名字,不过处理时使用int值也是可以的 |
map<K,V> | object | {"k1":v1,...} | 所有的key都会被转换成字符串 |
repeated V | array | [v1, ...] | null 会被解析城空的列表 |
bytes | base64 string | "YWJjMT..." | 编码时会自动使用带padding的标准Base64编码成字符串 |
int32/fixed32/uint32 | number | 1, -10, 0 | JSON值会是一个10进制数字,解析时数字或者字符串都可以接受 |
int64/fixed64/uint64 | string | "1", "-10" | 由于64位整数已经超出了JSON number的表示范围,编码解码都是用string |
float/double | number | 1.1, -10.0, "NaN", "Infinity","-Infinity" | 编码时会被做成number或特殊字符串,解码时数字或字符串都可以 |
Any | object | {"@type":"url", "f": v, ...} | @type暗示了真实的数据类型,如果Any中包含了一个值是特定的原生JSON数据,则会直接被解析出来 {"@type": xxx, "value": yyy} |
Timestamp | string | "1972-01-01T10:00:20.021Z" | RFC3339,尾部小数点后可以有0,3,6,9位数字 |
Duration | string | "1.0002s", "1s" | 尾部必须是s结尾,前面可以使用很多小数精度,但精度范围要在纳秒范围内 |
struct | object | {...} | see struct.proto |
包装类型(别名) | 与实际对应的类型行为保持一致 | ||
Empty | object | {} | 空对象 |
NullValue | null | JSON null |
在渲染JSON时,默认proto3不会输出值与默认值相等的字段,除非特别通过option指定
使用protoc
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
编码规范
文件名使用蛇形:
lower_snake_case.proto
文件格式
- 一行最长80字符
- 2空格缩进
文件结构
- License header
- File overview
- Syntax
- Package
- Imports (sorted)
- File options
- Everything else
重复字段(数组)
使用复数形式:
repeated string keys = 1;
repeated MyMessage accounts = 17;
枚举
枚举使用C语言的标准形式:全大写,下划线
Service
Service使用CamelCase
需要避免的
required和groups,这是给proto2用的,proto3不需要
protobuf文档翻译-安装,数据格式及编码规范的更多相关文章
- win10下安装PHP_CodeSniffer 检查编码规范
PHP CodeSniffer是PEAR中的一个用PHP5写的一个PHP的代码风格检测器,它根据预先设定好的PHP编码风格和规则,去检查应用中的代码风格情况是否有违反一组预先设置好的编码标准,内置了Z ...
- 阿里巴巴Java编码规范插件安装使用指南
编码规范插件安装使用指南 阿里技术公众号公布的<阿里巴巴Java开发规约>,瞬间引起全民代码规范的热潮,后又发布了PDF的终极版,大家踊跃留言,期待配套的静态扫描工具开放出来. 为了让开发 ...
- C#编码规范 转 http://www.cnblogs.com/wulinfeng/archive/2012/08/31/2664720.html
C#编码规范 1 规范目的 ……………………………………………………… 3 2 适用范围 ……………………………………………………… 3 3 代码注释 ………………………………………………… ...
- c#编码规范
1 规范目的 --------------------- 3 2 适用范围 --------------------- 3 3 代码注释 --------------------- 3 3.1 ...
- 资料推荐--Google Java编码规范
之前已经推荐过Google的Java编码规范英文版了: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html 虽然这篇文章的 ...
- PSR : php编码规范
诸王混战 关于开发标准这块,可以说一直都是风格迥异,各家都有各家的玩法,民间更是个人玩个人的.目前我们国内比较出名的几个框架(Yii,Laravel) 都已经支持Composer并且加入了PHP-FI ...
- 推荐的PHP编码规范
推荐的PHP编码规范 发布时间: 2014-05-7 浏览次数:2754 分类: PHP教程 推荐的PHP编码规范 一 编辑器设置 1. 使用Tab缩进,不要使用空格 鉴于很多编辑器在保存文件时会自动 ...
- Objective-C 编码规范
Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...
- Objective-C开发编码规范:4大方面解决开发中的规范性问题
Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...
随机推荐
- Java文件系统
Java7 引入了新的输入/输出2(NIO.2)API并提供了一个新的I/O API. 它向Java类库添加了三个包:java.nio.file,java.nio.file.attribute和jav ...
- Feign 系列(04)Contract 源码解析
Feign 系列(04)Contract 源码解析 [TOC] Spring Cloud 系列目录(https://www.cnblogs.com/binarylei/p/11563952.html# ...
- node+webpack+vue的环境搭建
一般第一次搭建环境的时候,多多少少还是会出点状况的.这个时候多去百度,看牛人怎么解决,然后跟着尝试,多试几遍还是能解决的. 先说一下我安装的过程吧 1.我一开始按照官网的来搭建,失败了.报错内容是 ...
- 【HDUOJ】4280 Island Transport
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4280 题意:有n个岛屿,m条无向路,每个路给出最大允许的客流量,求从最西的那个岛屿最多能运用多少乘客到 ...
- 微信小程序开发系列之Hello World
第一步:注册 在微信公众平台官网首页,点击注册.(相关文档可以找到,这里不再累述,望见谅.) 微信小程序注册成功后界面 第二步:编辑器.开发工具 我们假定你已经申请注册好微信小程序了,我们选定一个代码 ...
- 框架_mybatis2使用注解
在dao中使用注解: package cn.dao; import cn.mepu.User; import org.apache.ibatis.annotations.Select; import ...
- 召回率、AUC、ROC模型评估指标精要
混淆矩阵 精准率/查准率,presicion 预测为正的样本中实际为正的概率 召回率/查全率,recall 实际为正的样本中被预测为正的概率 TPR F1分数,同时考虑查准率和查全率,二者达到平衡,= ...
- ES6 简化对象写法
简化的对象写法 * 省略同名的属性值 * 省略方法的function <!DOCTYPE html> <html lang="en"> <head&g ...
- Centos7.5 安装sonarqube-7.1
下载sonarqube-7.1 wget -t 0 -c https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.1.z ...
- windows 登陆服务器
点击电脑的左下方开始,然后输入远字,如下图,就可以招到远程桌面了. 点击远程桌面就进入下图界面了.默认情况下,是在常规这个选项卡. 我们切换到显示,可以调节远程桌面的大小,一般我们设置成全屏显示.只要 ...