Protobuf3 Any类型

Any消息类型允许您将消息作为嵌入类型,而不需要它们 .proto定义。Any包含任意序列化的消息(字节),以及一个URL,该URL充当该消息的全局唯一标识符并解析为该消息的类型。要使用Any类型,你需要导入google/protobuf/any.proto.

import "google/protobuf/any.proto";

message ErrorStatus {
  string message = 1;
  repeated google.protobuf.Any details = 2;
}

指定消息类型的默认类型URL是type.googleapis.com/packagename.messagename.

不同的语言实现将支持运行时库助手以typesafe方式打包和解压缩ANY类型的值——例如,在Java中,任何类型都有特殊的pack()和unpack()访问器,而在c++中有PackFrom()和UnpackTo()方法:

// Storing an arbitrary message type in Any.
NetworkErrorDetails details = ...;
ErrorStatus status;
status.add_details()->PackFrom(details); // Reading an arbitrary message from Any.
ErrorStatus status = ...;
for (const Any& detail : status.details()) {
  if (detail.Is<NetworkErrorDetails>()) {
    NetworkErrorDetails network_error;
    detail.UnpackTo(&network_error);
    ... processing network_error ...
  }
}

目前正在开发用于处理ANY类型的运行时库。

如果您已经熟悉proto2语法,ANY类型会替换扩展名。

Protobuf3 Oneof

如果您有一条包含许多字段的消息,并且最多同时设置一个字段,您可以使用其中oneof功能来强制执行此行为并节省内存。

Oneof 字段类似于常规字段,除了Oneof共享内存的所有字段之外,最多可以同时设置一个字段。设置Oneof 的任何成员都会自动清除所有其他成员。您可以使用case()或WhichOneof()方法检查Oneof 中的哪个值被设置(如果有的话),具体取决于您选择的语言。

使用Oneof

在您的 .proto中定义一个oneof 关键字后跟着oneof 名称,在本例中为test_oneof:

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

然后将您的oneof字段添加到oneof定义中。您可以添加任何类型的字段,但不能使用重复字段。

在生成的代码中,oneof字段具有与常规字段相同的setter和getter方法。您还可以获得一种特殊的方法来检查中的哪个值(如果有的话)被设置。你可以在相关的API参考中找到更多关于你选择的语言的API。

Oneof功能

设置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());

如果解析器遇到同一oneof的多个成员,则在解析的消息中只使用最后一个成员。

oneof不能重复。

反射APIs适用于oneof字段。

如果您正在使用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结尾:在下面的示例中,msg1将有一条子消息,msg2将有一个名字。

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的成员。

标签重用问题

将字段移入或移出:在序列化和解析消息后,您可能会丢失一些信息(一些字段将被清除)。但是,您可以安全地将单个字段移动到新的字段中,如果已知只有一个字段被设置,您也可以移动多个字段。

删除一个字段并将其添加回去:这可能会在消息序列化和解析后清除当前设置的一个字段。

拆分或合并其中一个:这与移动常规字段有类似的问题。

Protobuf3 Maps

如果要创建关联映射作为数据定义的一部分,协议缓冲区提供了一种方便快捷的语法:

map<key_type, value_type> map_field = N;

其中key_type可以是任何整数或字符串类型(除浮点类型和字节以外的任何标量类型)。请注意,枚举不是有效的key_type,value_type可以是除另一个映射之外的任何类型。

因此,例如,如果您想为一个项目创建map,其中每个项目消息都与一个字符串键相关联,您可以这样定义它:

map<string, Project> projects = 3;

映射字段不能重复。

map值线格式排序和map迭代排序未定义,因此您不能依赖于项目的map特定顺序。

为生成文本格式时。proto,地图按键排序。数字键按数字排序。

为.proto生成文本格式时,map按键排序。数字键按数字排序。

从线上解析或合并时,如果有重复的map键,则使用最后看到的键。从文本格式解析map时,如果存在重复的键,解析可能会失败。

如果为映射字段提供了键但没有值,则序列化该字段时的行为取决于语言。在c++、Java和Python中,该类型的默认值是序列化的,而在其他语言中,没有任何值是序列化的。

生成的map API目前可用于所有受支持的proto3语言。你可以在相关的API参考中找到更多关于你选择的语言的map API。

向后兼容性

map语法相当于线上的以下内容,因此不支持map的协议缓冲区实现仍然可以处理数据:

message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
} repeated MapFieldEntry map_field = N;

任何支持映射的协议缓冲区实现都必须生成和接受可以被上述定义的数据。

九.Protobuf3特殊类型的更多相关文章

  1. Gradle学习系列之九——自定义Task类型

    在本系列的上篇文章中,我们学习了多Project构建,在本篇文章中,我们将学到如何自定义Task类型. 请通过以下方式下载本系列文章的Github示例代码: git clone https://git ...

  2. 浩哥解析MyBatis源码(九)——Type类型模块之类型处理器注册器(TypeHandlerRegistry)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6709157.html 1.回顾 上一篇研究的是类型别名注册器TypeAliasRegist ...

  3. 从零开始学习PYTHON3讲义(九)字典类型和插入排序

    <从零开始PYTHON3>第九讲 第六讲.上一讲我们都介绍了列表类型.列表类型是编程中最常用的一种类型,但也有挺明显的缺陷,比如: data = [5,22,34,12,87,67,3,4 ...

  4. MyBatis源码解析(九)——Type类型模块之类型处理器注册器(TypeHandlerRegistry)

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6709157.html 1.回顾 上一篇研究的是类型别名注册器TypeAliasRegist ...

  5. javaScript事件(九)事件类型之触摸与手势事件

    一.触摸事件 touchstart:当手指触摸屏幕时触发:即使已经有一个手指放在了屏幕上也会触发. touchmove:当手指在屏幕上滑动时连续地触发.在这个世界发生期间,调用preventDefau ...

  6. 《Java编程思想》笔记 第十九章 枚举类型

    1.基本enum特征 所有创建的枚举类都继承自抽象类 java.lang.Enum; 一个枚举类,所有实例都要在第一句写出以 ,隔开. 如果只有实例最后可以不加 : 枚举类因为继承了Enum,所以再不 ...

  7. Struts2学习九----------处理结果类型(input)

    © 版权声明:本文为博主原创文章,转载请注明出处 Struts2处理结果类型 - SUCCESS:Action正确的执行完成,返回相应的视图,success是name属性的默认值 - ERROR:表示 ...

  8. 【原创】go语言学习(九)指针类型

    目录 变量和内存地址 指针类型 值拷贝和引用拷贝 变量和内存地址 1.每个变量都有内存地址,可以说通过变量来操作对应大小的内存 var a int32 a = 100 fmt.Printf(“%d\n ...

  9. C#6.0语言规范(四) 类型

    C#语言的类型分为两大类:值类型和引用类型.值类型和引用类型都可以是泛型类型,它们采用一个或多个类型参数.类型参数可以指定值类型和引用类型. type : value_type | reference ...

随机推荐

  1. python 实现微信发送消息

    背景:利用Python来登入你个人的手机微信,之后向朋友发送消息,发送的消息可以来源于网页.下面的例子就是取得当前日元的汇率,之后发送自己的某一个朋友的手机上 环境:Python3,JetBrains ...

  2. 【Linux】多线程入门详解

    背景知识: 1.每次进程切换,都存在资源的保持和恢复动作,即上下文切换 2.进程的引入虽然可以解决多用户的问题,但是进程频繁切换的开销会严重影响系统性能 3.同一个进程内部有多个线程,这些线程共享的是 ...

  3. mvn: command not found in Jenkins slave

    在Jenkins上添加了一个slave node, 并绑定了一个团队项目,通过shell来执行后续操作,结果卡在了 mvn: command not found 其实这个node上是配置了maven的 ...

  4. [洛谷P5323][BJOI2019]光线

    题目大意:有$n$层玻璃,每层玻璃会让$a\%$的光通过,并把$b\%$的光反射.有一束光从左向右射过,问多少的光可以透过这$n$层玻璃 题解:事实上会发现,可以把连续的几层玻璃合成一层玻璃,但是要注 ...

  5. App开放接口API安全性之Token签名Sign的设计与实现

    前言 在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认证,那么这就需要用户提供一些信息,比如用户名密码等, ...

  6. Unity3D 跨平台原理

    Unity3D的跨平台原理核心在于对指令集CIL(通用中间语言)的应用. 机理 首先需要知道,Unity中的Mono是基于 通用语言架构(Common Language Infrastructure, ...

  7. Python之TensorFlow的变量收集、自定义命令参数、矩阵运算、梯度下降-4

    一.TensorFlow为什么要存在变量收集的过程,主要目的就是把训练过程中的数据,比如loss.权重.偏置等数据通过图形展示的方式呈现在开发者的眼前. 自定义参数:自定义参数,主要是通过Python ...

  8. cookie遇到java.lang.IllegalArgumentException: Control character in cookie value or attribute

    java.lang.IllegalArgumentException: Control character in cookie value or attribute. 该异常说明cookie中的val ...

  9. Java Runtime.exec()用法

    转自:https://www.cnblogs.com/mingforyou/p/3551199.html Java Runtime.exec()的使用 Sun的doc里其实说明还有其他的用法: exe ...

  10. go语言实现限流器

    本文:https://chai2010.cn/advanced-go-programming-book/ch5-web/ch5-06-ratelimit.html Ratelimit 服务流量限制 计 ...