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空格缩进

文件结构

  1. License header
  2. File overview
  3. Syntax
  4. Package
  5. Imports (sorted)
  6. File options
  7. Everything else

重复字段(数组)

使用复数形式:

repeated string keys = 1;
repeated MyMessage accounts = 17;

枚举

枚举使用C语言的标准形式:全大写,下划线

Service

Service使用CamelCase

需要避免的

required和groups,这是给proto2用的,proto3不需要

protobuf文档翻译-安装,数据格式及编码规范的更多相关文章

  1. win10下安装PHP_CodeSniffer 检查编码规范

    PHP CodeSniffer是PEAR中的一个用PHP5写的一个PHP的代码风格检测器,它根据预先设定好的PHP编码风格和规则,去检查应用中的代码风格情况是否有违反一组预先设置好的编码标准,内置了Z ...

  2. 阿里巴巴Java编码规范插件安装使用指南

    编码规范插件安装使用指南 阿里技术公众号公布的<阿里巴巴Java开发规约>,瞬间引起全民代码规范的热潮,后又发布了PDF的终极版,大家踊跃留言,期待配套的静态扫描工具开放出来. 为了让开发 ...

  3. C#编码规范 转 http://www.cnblogs.com/wulinfeng/archive/2012/08/31/2664720.html

    C#编码规范   1  规范目的 ……………………………………………………… 3 2  适用范围 ……………………………………………………… 3 3  代码注释 ………………………………………………… ...

  4. c#编码规范

    1  规范目的 --------------------- 3 2  适用范围 --------------------- 3 3  代码注释 --------------------- 3 3.1  ...

  5. 资料推荐--Google Java编码规范

    之前已经推荐过Google的Java编码规范英文版了: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html 虽然这篇文章的 ...

  6. PSR : php编码规范

    诸王混战 关于开发标准这块,可以说一直都是风格迥异,各家都有各家的玩法,民间更是个人玩个人的.目前我们国内比较出名的几个框架(Yii,Laravel) 都已经支持Composer并且加入了PHP-FI ...

  7. 推荐的PHP编码规范

    推荐的PHP编码规范 发布时间: 2014-05-7 浏览次数:2754 分类: PHP教程 推荐的PHP编码规范 一 编辑器设置 1. 使用Tab缩进,不要使用空格 鉴于很多编辑器在保存文件时会自动 ...

  8. Objective-C 编码规范

    Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...

  9. Objective-C开发编码规范:4大方面解决开发中的规范性问题

    Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...

随机推荐

  1. Codeforces 1189C Candies!

    题目链接:http://codeforces.com/problemset/problem/1189/C 思路:前缀和. AC代码: #include<bits/stdc++.h> usi ...

  2. pcre2 正则库

    \S+ 不能匹配到字符串末尾的最后一个字段

  3. nuxt 利用lru-cache 做服务器数据请求缓存

    // 运行与服务端的js // node.js lru-cache import LRU from 'lru-cache' const lruCache = LRU({ // 缓存队列长度 max: ...

  4. 2018-8-10-win10-uwp-反射

    title author date CreateTime categories win10 uwp 反射 lindexi 2018-08-10 19:17:19 +0800 2018-2-13 17: ...

  5. 2019-3-15-在-Windows-Defender-设置文件夹白名单提升-VisualStudio-编译速度

    title author date CreateTime categories 在 Windows Defender 设置文件夹白名单提升 VisualStudio 编译速度 lindexi 2019 ...

  6. robotframework+python3+selenium之常用情景---第四集

    1.切换浏览器 2.切换frame/iframe 3.截图保存 3.1导入Screenshot包 3.2 编写自动化测试之截图 4.后续再补充

  7. Centos 安装php Imagick 扩展

    从 centos 仓库安装 首先安装 php-pear php-devel,gcc三个软件包 yum install php-pear php-devel gcc 通过 yum 安装Centos 官方 ...

  8. wordpress非弹窗表单多文件上传插件

    插件名:Drag and Drop Multiple File Upload - Contact Form 7 (ps:如果是弹窗表单,不要使用这个插件Drag and Drop Multiple F ...

  9. DELPHI 异常处理2

    今天在写用ADO从EXCEL导入数据的程序时,出现个错误,弄了很久都弄不好,最后还是用异常处理解决掉了. 数据中日期在导入之前要转换成日期格式,虽然说一个strtodate就可以转好了,但是数据中的日 ...

  10. NX二次开发-对话框解锁UF_UI_unlock_ug_access

    VC/MFC调用UG Dialog要进入加锁状态 加锁 UF_UI_lock_ug_access ( UF_UI_FROM_CUSTOM ); 此处为UF_UI_select的函数 解锁 UF_UI_ ...