Oneof - Oneof结构

如果消息包含多个字段,并且最多只能同时设置一个字段,则可以使用oneof功能强制执行此行为并节省内存。

oneof字段与常规字段类似,但oneof共享内存中的所有字段除外,并且oneof最多只能同时设置一个字段。设置oneof的任何成员将自动清除所有其他成员。您可以使用特殊的case()WhichOneof()方法检查oneof中设置了哪个值(如果有被设置),具体取决于您选择的语言。

使用oneof结构

要在.proto中定义oneof结构,请使用oneof关键字后跟oneof名称。请看示例test_oneof

message SampleMessage {
oneof test_oneof {
string name = 4;
SubMessage sub_message = 9;
}
}

然后将oneof字段添加到oneof定义。你可以添加任意类型的字段,除了maprepeated类型的字段。

在生成的代码中,oneof字段与常规字段一样具有getter(访问器)和setter(设置器)。您还可以使用一种特殊的方法来检查oneof结构中设置了哪个值(如果有的话)。您可以在相关的API参考中找到有关所选语言的oneof API的更多信息。

oneof的功能

  • 设置oneof字段将自动清除oneof的所有其他成员。因此,如果您设置了几个字段中的一个,那么只有最后设置的字段有效。
SampleMessage message;
message.set_name("name");
CHECK(message.has_name());
message.mutable_sub_message(); // Will clear name field.
CHECK(!message.has_name());
  • 如果解析器在wire上遇到同一个oneof的多个成员,则在解析的消息中只使用看到的最后一个成员。
  • oneof结构不能使用repeated修饰符。
  • 反射API适用于oneof字段。
  • 如果将oneof字段设置为默认值(例如将int32类型的oneof字段设置为0),则将设置该oneof字段的case,并且该值将在wire上序列化。
  • 如果使用C++,请确保代码不会导致内存崩溃。下面的示例代码将崩溃,因为在调用set_name()方法时已经删除了sub_message
SampleMessage message;
SubMessage* sub_message = message.mutable_sub_message();
message.set_name("name"); // Will delete sub_message
sub_message->set_... // Crashes here
  • 同样在C++中,如果你使用Swap()方法交换两条使用了oneof结构的消息,每条消息都将以另外一条消息的oneof case结束:在下面的示例中,msg1将有一个sub_message字段,msg2将有一个name字段。
SampleMessage msg1;
msg1.set_name("name");
SampleMessage msg2;
msg2.mutable_sub_message();
msg1.swap(&msg2);
CHECK(msg1.has_sub_message());
CHECK(msg2.has_name());

向后(下)兼容问题

添加或删除oneof字段时要小心。如果检查oneof字段的值返回None/NOT_SET,则可能意味着此oneof尚未设置或已将其设置为oneof的其他版本中的字段。因为无法知道wire的未知字段是否是其中一个字段的成员,所以无法区分两者之间的区别。

标签重用问题
  • 将字段移入或移出oneof:消息序列化和解析后,可能会丢失一些信息(某些字段将被清除)。但是,您可以安全地将single字段移动到新的oneof字段中,并且如果已知只设置了一个字段,则可以移动多个字段。
  • 删除oneof字段并将其加回:这可能会在序列化和解析消息后清除当前设置的oneof字段。
  • 拆分或合并oneof字段:这与移动常规字段有类似的问题

原文:https://www.cnblogs.com/itheo/p/14273518.html

作者:Theo·Chan

版权:本文版权归作者和博客园共有

转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接,否则必究法律责任

最新文章

  1. MVC API 权限控制
  2. Laravel 使用多个数据库的问题。
  3. AMap公交线路查询
  4. 遍历Map
  5. SQL——用户定义函数
  6. js遍历jsonTree
  7. Linux之date
  8. 【Andorid------手势识别】GestureDetector和SimpleOnGestureListener的使用教程(转)——
  9. arm-linux-gcc-4.3.2安装步骤
  10. $.extend()和$.fn.extend()用法和区别
  11. 命令删除visualstudio.com云端项目(TFS)
  12. vijos1027题解
  13. bootstrap&NPM淘宝代理镜像
  14. 开启Linux的share
  15. 深入浅出KNN算法(一) KNN算法原理
  16. 很漂亮的PHP验证码(记录)
  17. shell =~ 引发的思考
  18. 解决:Tomcat 局域网IP地址 访问不了
  19. C&C++内存布局
  20. DROP语句总结

热门文章

  1. 第四章节 BJROBOT 线速度校正 【ROS全开源阿克曼转向智能网联无人驾驶车】
  2. LeapMotion控制器 java语言开发笔记--(Java开发环境的准备)
  3. SQL Server解惑——为什么ORDER BY改变了变量的字符串拼接结果
  4. ElasticSearch教程——自定义分词器(转学习使用)
  5. 《Go 语言并发之道》读后感 - 第一章
  6. promise引用自吕大豹
  7. TensorFlow 基础概念
  8. 【SpringBoot1.x】SpringBoot1.x 缓存
  9. 【C++】《Effective C++》第二章
  10. 【MYSQL】MySQL5.6.37二进制安装