protobuf extend字段C++的使用方式
前段时间参与一个多方开发的项目时,使用的某个proto文件中用到了extend字段的定义。在网上找了一圈使用方式,最终在只在Google的proto-buffer官网中看到,故此做个总结记录。extend字段的作用
extend字段是用来对原有的message类型进行扩展的。在某些场景下,可能在定义了一个基础的消息类型之后,不同的使用方需要在这个基础的消息类型上添加自己的独有字段。又或者在后续的功能升级过程中需要对该消息类型增加新的字段。这个时候预先定义了extend字段的话,就可以直接对消息进行扩展,而不用修改原来的proto文件修改消息类型的定义了。
一个典型的使用场景如统一的数据管理平台,不同的使用方上传的数据使用的字段是不一样的,由平台方把所有可能使用到的字段写到同一份proto文件中显然是不可能的。如记录商品信息的数据需要的字段可能是商品名、商品价格、生产日期等,而记录职员信息的数据需要的字段是姓名、年龄、职位、工龄等。此时,平台接口定义的消息类型可以只包含诸如时间、使用者等统一字段,同时预留出足够的extend字段由使用者自行定义。
extend proto的定义
首先是平台定义自己需要用到的字段,并预留出可扩展的字段,下面的proto中的编号100~10000即为预留字段。
package xuetu;
message base {
optional uint64 timestamp = 1;
repeated string owner = 2;
extensions 100 to 10000;
}
记录职员信息的数据proto就可以对上面的字段进行扩展并定义自己需要的字段,注意字段的id值只能是预留的extension范围。其中main.proto为原始定义的proto文件名。
package xuetu;
import "main.proto";
extend base {
optional string name = 100;
repeated string res= 101;
}
C++对extend字段的访问方式
与正常定义的message字段不同,extend增加的字段生成的cc和h文件中,没有针对每个字段都产生对应的“set_字段名”等函数用来设置、获取字段值。
对于extend字段,统一由HasExtension(), ExtensionSize(), ClearExtension(), GetExtension(), SetExtension(), MutableExtension(), AddExtension(), SetAllocatedExtension()和 ReleaseExtension()这几个函数进行操作。每个函数的第一个参数为需要操作的字段id名,后续参数与普通字段的操作函数类似。以下为一个根据上文的proto写到简单的示例程序,main.pb.h和person.pb.h分别为对应proto使用protoc生成的头文件。最后为程序输出的结果。
#include "main.pb.h"
#include "person.pb.h"
#include <iostream>
using namespace xuetu;
int main() {
base test;
//普通定义的optional、required字段,如timestamp字段
//使用set_timestamp()设置
//timestamp()获取
std::cout << &#34;========================timestamp==============&#34; << std::endl;
test.set_timestamp(1234);
std::cout << &#34;timestamp: &#34; << test.timestamp() << std::endl;
std::cout << &#34;===============================================&#34; << std::endl;
std::cout << std::endl;
//对于repeated字段owner
//使用add_owner()增加值
//使用owner_size()获取值的数量
//使用owner(index)获取值
std::cout << &#34;========================owner==================&#34; << std::endl;
test.add_owner(&#34;zhangsan&#34;);
test.add_owner(&#34;lisi&#34;);
test.add_owner(&#34;wangwu&#34;);
for (int i = 0; i < test.owner_size(); i++) {
std::cout << &#34;index:&#34; << i << &#34;, value:&#34; << test.owner(i) << std::endl;
}
std::cout << &#34;===============================================&#34; << std::endl;
std::cout << std::endl;
//对于extend扩展的optional、required字段
//使用SetExtension()设置值
//使用GetExtension()获取值
std::cout << &#34;========================name===================&#34; << std::endl;
test.SetExtension(name, &#34;xuetu&#34;);
std::cout << &#34;name:&#34; << test.GetExtension(name) << std::endl;
std::cout << &#34;===============================================&#34; << std::endl;
std::cout << std::endl;
//对于extend扩展的repeated字段
//使用AddExtension()增加值
//使用ExtensionSize()获取值的数量
//使用GetExtension()获取值
std::cout << &#34;=======================res=====================&#34; << std::endl;
test.AddExtension(res, &#34;res0&#34;);
test.AddExtension(res, &#34;res1&#34;);
test.AddExtension(res, &#34;res2&#34;);
for (int i = 0; i < test.ExtensionSize(res); i++) {
std::cout << &#34;index:&#34; << i << &#34;, value:&#34; << test.GetExtension(res, i) << std::endl;
}
std::cout << &#34;===============================================&#34; << std::endl;
std::cout << std::endl;
return 0;
}
页:
[1]