Protobuf 中的 Oneof kind 与 Enum

Vic*_*Cui 12 protocol-buffers proto

protobuf3 中使用 Enum 和 oneof kind 有什么区别?据我所知,枚举将字段限制为预定义的一组值之一,但 oneof 类型也是如此。

Bar*_*art 5

枚举是命名的数字。您可以在枚举定义中定义名称并为它们分配一个值。枚举的设置值应始终为零。

enum State {
  A = 0;
  B = 1;
  C = 2;
}
Run Code Online (Sandbox Code Playgroud)

接下来您可以在任何消息中使用此枚举

message Update {
  State currentState = 1;
  State previousState = 2;
}
Run Code Online (Sandbox Code Playgroud)

oneof是非常不同的东西它允许您发送不同的类型,但仅为它们分配有限的内存。这是因为您一次只能设置其中一种类型。这类似于unionC/C++ 中的或std::variantC++17 中的。

以这个例子为例,我们在 oneof 中定义了一条消息、一个整数和一个双精度数。

// The message in our oneof
message someMsg {
  // Multiple fields
}

// The message holding our oneof
message msgWithOneof {

  oneof theOneof {
    someMsg msg     = 1;
    int32   counter = 2;
    double  value   = 3;
  }
  // Feel free to add more fields her of before the oneof
}
Run Code Online (Sandbox Code Playgroud)

您一次只能设置msgcounter或。value如果您设置另一个,这将清除其他字段。

假设 C/C++ 实现最大的字段将决定分配的内存量。假设someMsg是最大的,设置整数或双精度数不会有问题,因为它们适合相同的空间。如果不使用 oneof,分配的总内存将是 的总和sizeof(someMsg) + sizeof(int32) + sizeof(double)

跟踪已设置的字段需要一些开销。在 google C++ 实现中,这有点存在变量。这类似于标记为可选的字段。

  • 除了“不同类型”之外,它还允许您表示相同的*类型*,但具有不同的语义 - 例如,`msgWithOneof.theOneof`还可以有一个额外的`double valueDelta = 4;`和`someMsg CriticalMessage = 5;`(但`theOneof`中最多可以有一个值在任何时候都有一个值) (2认同)