Language Guide (proto3) | proto3 语言指南(九)Oneof结构
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定义。你可以添加任意类型的字段,除了map和repeated类型的字段。
在生成的代码中,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字段:这与移动常规字段有类似的问题
Language Guide (proto3) | proto3 语言指南(九)Oneof结构的更多相关文章
- Swift语言指南(九)--基本运算符
原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...
- Swift5 语言指南(九) 闭包
闭包是自包含的功能块,可以在代码中传递和使用.Swift中的闭包类似于C和Objective-C中的块以及其他编程语言中的lambdas. 闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用 ...
- Language Guide (proto3) | proto3 语言指南(开篇)
前言 近日在学习gRPC框架的相关知识时接触到Protobuf(protocol-buffers,协议缓冲区),proto3等知识.网上很多文章/帖子经常把gRPC与proto3放在一起,为避免初学者 ...
- Language Guide (proto3) | proto3 语言指南(十五)生成类
Generating Your Classes - 生成类 要生成Java.Python.C++.Go.Ruby.ObjuleC或C代码,需要使用.proto文件中定义的消息类型,还需要在.proto ...
- Language Guide (proto3) | proto3 语言指南(十四)选项
Options - 选项 .proto文件中的单个声明可以使用许多 选项 进行注释.选项不会更改声明的总体含义,但可能会影响在特定上下文中处理声明的方式.可用选项的完整列表在google/protob ...
- Language Guide (proto3) | proto3 语言指南(十二)定义服务
Defining Services - 定义服务 如果要在RPC(Remote Procedure Call,远程过程调用)系统中使用消息类型,可以在.proto文件中定义RPC服务接口,协议缓冲区编 ...
- Protobuf 语言指南(proto3)
Protobuf 语言指南(proto3) Protocol Buffer是Google的语言中立的,平台中立的,可扩展机制的,用于序列化结构化数据 - 对比XML,但更小,更快,更简单.您可以定义数 ...
- Protocol Buffers(Protobuf) 官方文档--Protobuf语言指南
Protocol Buffers(Protobuf) 官方文档--Protobuf语言指南 约定:为方便书写,ProtocolBuffers在下文中将已Protobuf代替. 本指南将向您描述如何使用 ...
- Protobuf语言指南(转)
Protobuf语言指南 l 定义一个消息(message)类型 l 标量值类型 l Optional 的字段及默认值 l 枚举 l 使用其他消息类型 l 嵌套类型 l 更新一个消息类型 ...
随机推荐
- [leetcode]450. Delete Node in a BST二叉搜索树删除节点
二叉树变量只是一个地址 public static void main(String[] args) { TreeNode t = new TreeNode(3); help(t); System.o ...
- JavaSwing 船只停靠管理可视化(四)
JavaSwing 船只停靠管理可视化(一) JavaSwing 船只停靠管理可视化(二) JavaSwing 船只停靠管理可视化(三) JavaSwing 船只停靠管理可视化(四) JavaSwin ...
- 自定义 简单 底部tab
项目地址:https://gitee.com/jielov/music-netease-api.git 先创建三个页面 分别为 home.vue , classify.vue, my.vue . 以下 ...
- linux IP 注释
DEVICE=name,这里name是物理设备的名字(动态分配的PPP设备应当除外,它的名字是"逻辑名". IPADDR=addr, 这里addr是IP地址. NETMASK=ma ...
- WPF学习笔记01_XAML之简介
简介 XAML (发音"zammel" 咋么儿),用于实例化.NET对象的标记语言,主要用于构造WPF的用户界面.类似html标记语言. 通过XAML,程序员可以用代码的方式对界面 ...
- Vue css过渡 和 js 钩子过渡
css过渡 <transition name="slide"> <div v-show="!showChatInput" class=&quo ...
- PHP MySQLi extension is not loaded
PHP MySQLi extension is not loaded 如何解决呢? yum -y install mysqli.so huozhe yum -y install php-mysql
- 【Oracle】删除表空间
删除表空间如果是 SQL> DROP TABLEPSACE XXXX; 是无法将数据文件一同都删除的 想要删除表空间和数据文件需要如下操作: SQL> drop tablespace XX ...
- JMS监听Oracle AQ
该文档中,oracle版本为11g,jdk版本1.8,java项目为maven构建的springboot项目,springboot的版本为2.1.6,并使用了定时任务来做AQ监听的重连功能,解决由于外 ...
- Python小度
这只是一个对话器!还不能听歌(反正我也没在UNIT平台配置听歌的功能)! 反正最近也不知怎么的,就想做一个AI对话器语音识别和语音输出都不要,input()和print()就行本来准备用小爱的,但要实 ...