当前位置: 首页 > 工具软件 > Codename One > 使用案例 >

protobuf3 oneof

姬高澹
2023-12-01

前言

工作需要,需要用到 protobuf3 中的 oneof 来定义数据结构,在这里翻译一下 pb官方文档,oneof
(意译+机翻,塑料英语勿喷,欢迎指正)

内容

Oneof

If you have a message with many fields and where at most one field will be set at the same time, you can enforce this behavior and save memory by using the oneof feature.
如果你有一个 message 且里面有很多字段,但对于每个 message,你只会为至多一个字段赋值,那么这时候你就可以用 oneof 来强制遵循这种行为(为至多一个字段赋值)同时起到节省内存空间的效果。

Oneof fields are like regular fields except all the fields in a oneof share memory, and at most one field can be set at the same time. Setting any member of the oneof automatically clears all the other members. You can check which value in a oneof is set (if any) using a special case() or WhichOneof() method, depending on your chosen language.
除了 oneof 中所有字段共享内存并且最多只可以同时设置一个字段外,oneof 字段跟常规字段没有太大区别。设置 oneof 的任何成员都会自动清除所有其他成员。你可以通过使用 case() 或者 WhichOneof() 来确认 oneof 设置了哪个字段,用哪种方法取决于你使用的编程语言。

Using Oneof

To define a oneof in your .proto you use the oneof keyword followed by your oneof name, in this case test_oneof:
要在 .proto 文件中定义 oneof,你需要使用 oneof 关键字,后面跟着 oneof 字段的名称,就像本例 test_oneof

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

You then add your oneof fields to the oneof definition. You can add fields of any type, except map fields and repeated fields.( If you need to add a repeated field to a oneof, you can use a message containing the repeated field. 【protobuf2】)
然后,你可以将字段添加到 oneof 中。 你可以添加任何类型的字段,map 字段和 repeated 字段除外。

In your generated code, oneof fields have the same getters and setters as regular fields. You also get a special method for checking which value (if any) in the oneof is set. You can find out more about the oneof API for your chosen language in the relevant API reference.
在你写的代码中,oneof 字段具有跟常规字段相同的 getter 和 setter。你还可以获得一种特殊的方法来确认 oneof 设置了哪个值(如果有的话)。你可以在相关文档中找到有关所选语言的 oneof API 的更多信息。

Oneof Features

Setting a oneof field will automatically clear all other members of the oneof. So if you set several oneof fields, only the last field you set will still have a value.
设置一个 oneof 的成员都会自动清除所有其他成员,所以如果你多次设置 oneof 的成员,泽只有最后一次设置的成员有值

SampleMessage message;
message.set_name("name");
CHECK(message.has_name());
message.mutable_sub_message();   // Will clear name field.
CHECK(!message.has_name());

If the parser encounters multiple members of the same oneof on the wire, only the last member seen is used in the parsed message.
如果解析器在线路上遇到同一个 oneof 的多个成员,则在解析的消息中只使用最后一个看到的成员。

A oneof cannot be repeated.
oneof 不能重复

Reflection APIs work for oneof fields.
反射 API 适用于 oneof 字段。

If you set a oneof field to the default value (such as setting an int32 oneof field to 0), the “case” of that oneof field will be set, and the value will be serialized on the wire.
如果将 oneof 字段设置为默认值(例如将 int32 oneof 字段设置为 0),则会设置该 oneof 字段的“大小写”,并且该值将在线上序列化。

If you’re using C++, make sure your code doesn’t cause memory crashes. The following sample code will crash because sub_message was already deleted by calling the set_name() method.
如果您使用 C++,请确保您的代码不会导致内存崩溃。 以下示例代码将崩溃,因为 sub_message 已通过调用 set_name() 方法删除。

SampleMessage message;
SubMessage* sub_message = message.mutable_sub_message();
message.set_name("name");      // Will delete sub_message
sub_message->set_...            // Crashes here

Again in C++, if you Swap() two messages with oneofs, each message will end up with the other’s oneof case: in the example below, msg1 will have a sub_message and msg2 will have a name.
同样在 C++ 中,如果您使用 oneofs Swap() 两条消息,则每条消息都会以另一个的 oneof 情况结束:在下面的示例中,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());

Backwards-compatibility issues

向后兼容性问题

Be careful when adding or removing oneof fields. If checking the value of a oneof returns None/NOT_SET, it could mean that the oneof has not been set or it has been set to a field in a different version of the oneof. There is no way to tell the difference, since there’s no way to know if an unknown field on the wire is a member of the oneof.
添加或删除其中一个字段时要小心。 如果检查 oneof 的值返回 None/NOT_SET,则可能意味着 oneof 尚未设置或已设置为 oneof 不同版本中的字段。 没有办法区分,因为无法知道线路上的未知字段是否是 oneof 的成员。

Tag Reuse Issues
标签重用问题
Move fields into or out of a oneof: You may lose some of your information (some fields will be cleared) after the message is serialized and parsed. However, you can safely move a single field into a new oneof and may be able to move multiple fields if it is known that only one is ever set.
将字段移入或移出 oneof:在消息被序列化和解析后,您可能会丢失一些信息(某些字段将被清除)。 但是,您可以安全地将单个字段移动到新的 oneof 中,并且如果知道只设置了一个字段,则可以移动多个字段。

Delete a oneof field and add it back: This may clear your currently set oneof field after the message is serialized and parsed.
删除 oneof 字段并重新添加:这可能会在消息被序列化和解析后清除您当前设置的 oneof 字段。

Split or merge oneof: This has similar issues to moving regular fields.
拆分或合并其中一个:这与移动常规字段有类似的问题。

 类似资料:

相关阅读

相关文章

相关问答