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

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

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

Language Guide (proto3) | proto3 语言指南(九)Oneof结构的更多相关文章

  1. Swift语言指南(九)--基本运算符

    原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...

  2. Swift5 语言指南(九) 闭包

    闭包是自包含的功能块,可以在代码中传递和使用.Swift中的闭包类似于C和Objective-C中的块以及其他编程语言中的lambdas. 闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用 ...

  3. Language Guide (proto3) | proto3 语言指南(开篇)

    前言 近日在学习gRPC框架的相关知识时接触到Protobuf(protocol-buffers,协议缓冲区),proto3等知识.网上很多文章/帖子经常把gRPC与proto3放在一起,为避免初学者 ...

  4. Language Guide (proto3) | proto3 语言指南(十五)生成类

    Generating Your Classes - 生成类 要生成Java.Python.C++.Go.Ruby.ObjuleC或C代码,需要使用.proto文件中定义的消息类型,还需要在.proto ...

  5. Language Guide (proto3) | proto3 语言指南(十四)选项

    Options - 选项 .proto文件中的单个声明可以使用许多 选项 进行注释.选项不会更改声明的总体含义,但可能会影响在特定上下文中处理声明的方式.可用选项的完整列表在google/protob ...

  6. Language Guide (proto3) | proto3 语言指南(十二)定义服务

    Defining Services - 定义服务 如果要在RPC(Remote Procedure Call,远程过程调用)系统中使用消息类型,可以在.proto文件中定义RPC服务接口,协议缓冲区编 ...

  7. Protobuf 语言指南(proto3)

    Protobuf 语言指南(proto3) Protocol Buffer是Google的语言中立的,平台中立的,可扩展机制的,用于序列化结构化数据 - 对比XML,但更小,更快,更简单.您可以定义数 ...

  8. Protocol Buffers(Protobuf) 官方文档--Protobuf语言指南

    Protocol Buffers(Protobuf) 官方文档--Protobuf语言指南 约定:为方便书写,ProtocolBuffers在下文中将已Protobuf代替. 本指南将向您描述如何使用 ...

  9. Protobuf语言指南(转)

    Protobuf语言指南 l  定义一个消息(message)类型 l  标量值类型 l  Optional 的字段及默认值 l  枚举 l  使用其他消息类型 l  嵌套类型 l  更新一个消息类型 ...

随机推荐

  1. Mac电脑 Android Studio连接小米手机

    1.设置>关于本机>点击5下MIUI版本>激活开发者模式 2.设置>更多设置>开发者选项>开启开发者选项>开启USB调试>开启USB安装>开启显示 ...

  2. 四元数和旋转(Quaternion & rotation)

    四元数和旋转(Quaternion & rotation) 本篇文章主要讲述3D空间中的旋转和四元数之间的关系.其中会涉及到矩阵.向量运算,旋转矩阵,四元数,旋转的四元数表示,四元数表示的旋转 ...

  3. Oracle-序列-存储过程-视图-索引-触发器

    课程介绍 1. 约束(掌握) 2. 序列(掌握) 3. 索引(掌握) 4. 视图(掌握) 5. 存储过程(掌握) 6. 自定义函数(掌握) 7. 触发器(掌握) 数据库对象的命名规则 1.对象名称必须 ...

  4. LAMP搭建示例

    lamp介绍 其实就是由Linux+Apache+Mysql/MariaDB+Php/Perl/Python的一组动态网站或者服务器的开源软件,除Linux外其它各部件本身都是各自独立的程序,但是因为 ...

  5. Java核心类

    Java核心类的学习: 常用类库 io流 集合 多线程 网络编程 调试与优化 XML和JSON 枚举.注解和反射 设计模式

  6. spring cache 学习——@CachePut 使用详解

    1. 功能说明 当需要在不影响方法执行的情况下更新缓存时,可以使用 @CachePut,也就是说,被 @CachePut 注解的缓存方法总是会执行,而且会尝试将结果放入缓存(当然,是否真的会缓存还跟一 ...

  7. vue的路由组件挂载。

    vue通过多种方式可以将组件挂载到一个页面上.挂载方式有四种.其实也并不止四种.这里呢就简单的提四种方式去怎样挂载组件. 第一种就是作为标签形式挂载.前面也提到. 后面的就是一般的挂载组件和按需挂载组 ...

  8. epoll的陷阱

    Starvation 特别提出在ET模式下,因为需要一次性把数据读完,如果一次性通知的数据过大,有可能处理时间过长,导致同一线程其他的事件长时间等待.这个不仅仅是ET模式下,也不仅仅是epoll模型下 ...

  9. spring ioc踏出第一步

    spring IOC(容器) AOP(面向切面编程) IOC容器:他的功能就是可以整合像 Structs2 .Hibernate.Mybatis: IOC:控制反转:所谓的控制就是控制资源的获取方法, ...

  10. 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC

    文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...