protobuf 浅试
protobuf 是 Google 推出的语言独立,平台独立的针对序列化数据的组件,可以类比 xml, 但是比 xml 精简。
通过使用 protobuf 语法自定义想要的数据结构,接着用 protoc 命令就可以产生针对这种数据格式文件读写的各种语言(C/C++, Python, Java等)的 API.
Mac 上安装 protobuf
1 | brew install protobuf |
proto 语法
自定义序列化数据结构使用特殊的语法,创建 proto 文件,其包含如下内容
syntax= proto2 | proto3packagemessagefield[required | optional | repeated]typename[message]
tag
1 | syntax = "proto2" | "proto3“ |
message
一个 message 类型表示了一个可以序列化的结构。由若干个 field 组成
field
一个 field 由以下部分构成
typeproto支持的类型可见官网, 可以是用户自定义的 messagefield number
每个field最后包含一个独特数字,这个数字在二进制格式中标记这个field,当整个message投入使用后不应该再修改,这些Number可取的范围是, 但是 这个区间属于保留区,不应使用,否则会提示 FieldDescriptor::FieldDescriptor错误。field rulesingular
在一个组织良好的message中,这field可以出现一次或零次repeated
在一个组织良好的message中,这个field可以出现任意次数,值出现的顺序保留。
保留域
可以注明一个 field 是 reserved,可以标注其 field number 或者 name, 示例如下
1 | message Foo { |
reserved 标注意为未来可能会抛弃这个 field, 提示用户尽可能少使用这个 field, 每当 proto buffer compiler 编译这个 proto 文件生成 api 时都会给出相应的警告。
Enumeration
proto 中定义枚举类型的语法与 C++ 基本相同
1 | enum Corpus { |
注意,一定要有 0 值
Any
Any 类型可以保存任意类型的信息,直接将任何序列化的 message 看做看做字节串存储
oneof
类似 C++ 中的 union ,存储时只存储 oneof 域中的一个。
1 | message SampleMessage { |
当取其中一个域时,其他域自动会被删除,当使用 C++ 时要注意内存崩溃问题.
Maps
定义 Map 的语法如下
1 | map<key_type, value_type> map_field = N; |