diff --git a/hzh/TEST/gRPC.md b/hzh/TEST/gRPC.md index 6146233..1dacba8 100644 --- a/hzh/TEST/gRPC.md +++ b/hzh/TEST/gRPC.md @@ -91,8 +91,8 @@ D. 旧客户端把该字段当作空字符串处理 A. `oneof` 可以修饰 `repeated` 类型的字段,方便存储一组互斥值 B. Proto3 中 `oneof` 所有变体共享同一个零值 `NONE(0)`,所以反序列化时无法区分哪个变体被设置过 -C. 新增 oneof 变体会破坏旧客户端的兼容性 -D. oneof 中的每个成员必须使用不同的字段编号,且编号不能跨 oneof 组共用 +C. Proto3 会为 oneof 自动生成 IsXXX() setter 方法以支持精确的状态判断 +D. oneof 中的成员编号必须跨不同 oneof 组全局唯一 > [!tip]- Q3 答案 > **B — oneof 零值为 NONE(0),无法区分未设置状态** @@ -103,8 +103,8 @@ D. oneof 中的每个成员必须使用不同的字段编号,且编号不能 > **逐项分析:** > - ❌ A:`oneof` **不能**加 `repeated` 修饰符,因为 multiple 值和 oneof 互斥语义矛盾 > - ✅ B:正确。Proto3 没有 Optional 概念,当 all fields 都等于其默认值时,你无法知道用户到底传了 `"none"` 还是没传 -> - ❌ C:新增 oneof 变体是安全的——旧客户端会把它当成未知编号字段忽略 -> - ❌ D:oneof 内的成员只需在自己的 oneof 内唯一,不同 oneof 之间可以重用编号 +> - ❌ C:Proto3 **不会**为 oneof 自动生成任何 `IsXXX()` 方法。这正是 Proto3 oneof 的核心痛点——你无法通过 API 判断哪个变体被设置过(因为当所有值都等于默认值时,语义上就是不可区分的)。如果需要区分"未设置"和"设置为空值",必须使用 Well-Known Types 包装器。 +> - ❌ D:**错误**。Protobuf 规范只要求字段编号在同一个 oneof **内部**唯一,不同 oneof 之间可以重用编号(proto 的二进制编码只看 `(field_number, wire_type)`,不同 oneof 之间不会产生冲突) > > **如果需要精确表达"可选"**,推荐使用 Well-Known Types 中的 `StringValue` 包装: > ```proto