2023 年 6 月 29 日宣布的变更

于 2023 年 6 月 29 日宣布的 Protocol Buffers 相关变更。

长话短说: 我们计划在 2023 年下半年向开源项目发布 Protobuf 版本 (Editions)。虽然在初始版本发布时并非强制要求从 proto2/proto3 语法迁移到版本 (Editions) 语法,但我们鼓励您在软件项目的未来规划中考虑进行迁移。

Protobuf Editions

Protobuf 版本 (Editions) 取代了我们一直用于 Protocol Buffers 的 proto2 和 proto3 命名。您不再需要在 proto 定义文件的顶部添加 syntax = "proto2"syntax = "proto3",而是使用版本号,例如 edition = "2024",来指定文件的默认行为。版本 (Editions) 使该语言能够随着时间的推移逐步演进。

与旧版本中的硬编码行为不同,版本 (Editions) 将代表一系列“特性”的集合,每个特性都有一个默认值(行为),您可以覆盖这些默认值。特性是文件、消息、字段、枚举等上面的选项,用于指定 protoc、代码生成器和 protobuf 运行时的行为。当您的需求与所选版本的默认行为不匹配时,您可以在这些不同的级别(文件、消息、字段等)显式覆盖所需的行为。

版本 (Editions) 不会破坏现有的二进制文件,并且第一个版本的影响将非常小;它将建立基线,并将 proto2 和 proto3 定义合并为一个新的单一的定义格式。它不需要对您的代码进行任何更改。我们将提供一个名为 Prototiller 的工具来迁移 .proto 文件。以下示例展示了一个 proto2 定义文件和一个 proto3 文件,以及在使用 Prototiller 将它们转换为 Protobuf 版本 (Editions) 格式后各自的样子。

Proto2 语法

// proto2 file
syntax = "proto2";

message Player {
  // in proto2, optional fields have explicit presence
  optional string name = 1;
  // proto2 still supports the problematic "required" field rule
  required int32 id = 2;
  // in proto2 this is not packed by default
  repeated int32 scores = 3;

  enum Handed {
    HANDED_UNSPECIFIED = 0,
    HANDED_LEFT = 1,
    HANDED_RIGHT = 2,
    HANDED_AMBIDEXTROUS = 3,
  }

  // in proto2 enums are closed
  optional Handed handed = 4;
}

版本 (Editions) 语法

// Editions version of proto2 file
edition = "2023";

message Player {
  string name = 1;
  int32 id = 2 [features.field_presence = LEGACY_REQUIRED];
  repeated int32 scores = 3 [features.repeated_field_encoding = EXPANDED];

  enum Handed {
    // this overrides the default Edition 2023 behavior, which is OPEN
    option features.enum = CLOSED;
    HANDED_UNSPECIFIED = 0,
    HANDED_LEFT = 1,
    HANDED_RIGHT = 2,
    HANDED_AMBIDEXTROUS = 3,
  }

  Handed handed = 4;
}

下面是一个类似的 proto3 定义文件可能的样子:

Proto3 语法

// proto3 file
syntax = "proto3";

message Player {
  // in proto3, optional fields have explicit presence
  optional string name = 1;
  // in proto3 no specified field rule defaults to implicit presence
  int32 id = 2;
  // in proto3 this is packed by default
  repeated int32 scores = 3;

  enum Handed {
    HANDED_UNSPECIFIED = 0,
    HANDED_LEFT = 1,
    HANDED_RIGHT = 2,
    HANDED_AMBIDEXTROUS = 3,
  }

  // in proto3 enums are open
  optional Handed handed = 4;
}

版本 (Editions) 语法

// Editions version of proto3 file
edition = "2023";

message Player {
  string name = 1;
  int32 id = 2 [features.field_presence = IMPLICIT];
  repeated int32 scores = 3;

  enum Handed {
    HANDED_UNSPECIFIED = 0,
    HANDED_LEFT = 1,
    HANDED_RIGHT = 2,
    HANDED_AMBIDEXTROUS = 3,
  }

  Handed handed = 4;
}

虽然本主题中提供的示例展示了从 proto2 和 proto3 到使用 Protobuf 版本 (Editions) 的等效表示的直接转换,但您将能够根据项目需求混合和匹配这些设置。

特性有一个由版本 (Editions) 发布所管理的生命周期。例如,features.awesome_new_feature 可能会在 2031 版中添加,新行为将应用于所有未明确覆盖该新行为的定义。在 2033 版中,该新特性被弃用。覆盖仍然有效,但会提醒开发者需要尽快适应新的行为。在 2036 版中,该特性被移除,新行为将应用于所有 proto;此时将无法覆盖该新行为。

Editions lifecycle
图 1:版本 (Editions) 生命周期流程图

版本 (Editions) 计划大约每年发布一次。有关 Protobuf 版本 (Editions) 的更多信息,请参阅 https://protobuf.com.cn/editions/overview 上的概述。