yjz*_*ang 182 protocol-buffers grpc proto3
我最近使用gRPC与proto3,我已经注意到,required并optional在新的语法已被删除.
有人会解释为什么在proto3中删除了必需/可选项?这样的约束似乎对于使定义具有鲁棒性是必要的.
语法proto2:
message SearchRequest {
required string query = 1;
optional int32 page_number = 2;
optional int32 result_per_page = 3;
}
Run Code Online (Sandbox Code Playgroud)
语法proto3:
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*son 332
它的用处required一直是许多辩论和火焰战争的核心.双方都有大型营地.一个阵营喜欢保证价值存在并且愿意忍受其限制,但另一个阵营感到required危险或无益,因为它无法安全地添加或删除.
让我解释为什么required应该谨慎使用字段的原因.如果您已经在使用proto,则无法添加必填字段,因为旧应用程序将不提供该字段,并且应用程序通常不能很好地处理故障.您可以确保首先升级所有旧应用程序,但它很容易出错,如果您将protos存储在任何数据存储区中(即使是短暂的,如memcached)也无济于事.删除必填字段时也会出现同样的情况.
许多必需的领域"显然"需要,直到......他们不是.假设你有id一个Get方法的字段.这显然是必需的.除此之外,您可能需要将idfrom int 更改为string,或将int32更改为int64.这需要添加一个新muchBetterId字段,现在您将留下必须指定的旧id字段,但最终会被完全忽略.
当这两个问题结合起来时,有益required领域的数量变得有限,并且营地争论它是否仍然具有价值.反对者required不一定反对这个想法,而是它目前的形式.一些人建议开发一个更具表现力的验证库,它可以检查required更先进的东西name.length > 10,同时也确保有更好的故障模型.
Proto3整体似乎更倾向于简单,并且required删除更简单.但也许更有说服力,required当与其他功能结合使用时删除了proto3,例如删除原语的字段存在以及删除重写的默认值.
我不是一个protobuf开发者,在这个问题上我没有权威,但我仍然希望这个解释很有用.
小智 32
你可以在这个protobuf Github问题中找到解释:
我们删除了proto3中的必填字段,因为通常认为必填字段有害并且违反了protobuf的兼容性语义.使用protobuf的整个想法是,它允许您添加/删除协议定义中的字段,同时仍然完全向前/向后兼容较新/较旧的二进制文件.必填字段打破了这一点.您永远不能安全地向.proto定义添加必填字段,也不能安全删除现有的必填字段,因为这两个操作都会破坏电线兼容性.例如,如果向.proto定义添加必填字段,则使用旧定义构建的二进制文件将无法解析使用旧定义序列化的数据,因为旧数据中不存在必需字段.在一个复杂的系统中,.proto定义在系统的许多不同组件中广泛共享,添加/删除必需的字段可以轻松地降低系统的多个部分.我们已经多次看到由此造成的生产问题,并且谷歌内部的任何地方都禁止添加/删除必填字段.出于这个原因,我们完全删除了proto3中的必填字段.
删除"required"后,"optional"只是多余的,所以我们也删除了"optional".
可选字段在 protobuf 3.15 中返回
因为相关概念的正交分解很困难,并且 Protocol Buffers 设计以一种令人沮丧的方式组合了至少 4 个独立的概念:可空性(又名存在跟踪)、内容验证、有用的默认值和空间效率。
Proto2 允许字段为“必填”或“可选”,并允许指定默认值,但仅限于“可选”字段。
“可选”关键字在 3.12/3.15 中回归,用于状态跟踪。请参阅Field Presence 上的应用说明。
“required”关键字已被用作验证检查,这很不幸,因为 Protobuf 无法胜任验证工具的任务。它没有最小/最大值语法、长度或模式限制。更重要的是,它无法表达字段之间的数据值依赖关系(除了基本结构固有的关系)。
Protobuf 使用“默认”值作为初始构造值,并作为一种通过不发送这些值来减少消息大小的机制(在 proto3 中)。这有点不幸,因为能够为特定代码生成运行指定初始值对于生产者(“这是我想要在正常使用中发送的值”)或消费者(“也许我应该检查是否为空/不存在,但现在就好像发送“x”一样就足够了“)。
OTOH,如果未提供值,指定合同默认假设如何继续似乎确实会有所帮助。然而,能否做好这方面的工作通常取决于其他字段的值(或存在),而 Protobuf 无法做到这一点,因为同样(可以说很漂亮)缺乏复杂性,这使得它不适合数据验证。因此,如果您希望在面对缺失字段时表现良好,那么最好将显式存在检查与任何其他适当的数据检查结合起来。.... 至少在 3.12/3.15 以后你可以。...对于简单的情况,也许 0 左右的值就足够了。
| 归档时间: |
|
| 查看次数: |
66281 次 |
| 最近记录: |