vault backup: 2026-05-13 11:17:21
This commit is contained in:
@@ -316,6 +316,21 @@ if err != nil { ... }
|
||||
// native.Interface() → map[string]any
|
||||
```
|
||||
|
||||
### Any 与 Value 对比
|
||||
|
||||
| 维度 | `Any` | `Value` |
|
||||
|------|-------|---------|
|
||||
| **包裹对象** | 其他 protobuf 消息 | 任意 JSON 值(struct / list / string / number / bool / null) |
|
||||
| **类型信息** | 有 `@type`,运行时可校验 | 零类型信息 |
|
||||
| **反序列化** | `UnmarshalTo(&target)` — 强类型目标结构体 | 手动 `GetXXX()` — 裸 `interface{}` |
|
||||
| **灵活性** | ⚠️ 需在服务端注册类型 descriptor | ✅ 传什么 JSON 都行 |
|
||||
| **类比** | Go 的 `any`(interface{}),但带 type 标签 | 数据库里的 JSONB 字段 |
|
||||
| **典型场景** | 事件总线、插件架构、Generic Response Wrapper | 配置中心、审计日志、自由表单 |
|
||||
|
||||
### 一句话决策
|
||||
|
||||
如果你知道消息类型且想享受编译期生成的类型定义,用 `Any`;如果你连结构都不确定(比如纯 JSON 自由格式),用 `Value`。
|
||||
|
||||
> [!question] 思考题
|
||||
> `Any` 和 `Value` 都能包裹动态内容,该用哪个?记住一个原则:**如果你知道消息类型且想享受编译期检查,用 Any;如果你连结构都不确定(比如纯 JSON),用 Value。**
|
||||
|
||||
@@ -422,14 +437,14 @@ effectiveMask, _ := fieldmaskpb.New(changedFields...)
|
||||
|
||||
## 对比总结表格
|
||||
|
||||
| 特性 | Oneof | Wrapper | Any | Value |
|
||||
|------|-------|---------|-----|-------|
|
||||
| 类型安全 | ✅ compile-time | ✅ compile-time | ⚠️ runtime | ❌ 运行时 |
|
||||
| 单个可选 | ✅ 可用 | ✅(更简洁) | N/A | N/A |
|
||||
| 多值互斥 | ✅ 核心用途 | ❌ | N/A | N/A |
|
||||
| 动态类型 | ❌ | ❌ | ✅ | ✅ |
|
||||
| JSON 互转 | ⚠️ 需额外处理 | ✅ | ✅ | ✅ |
|
||||
| wire overhead | 低 | 低 | 中(需存 type_url) | 低 |
|
||||
| 特性 | Oneof | Wrapper | Any | Value |
|
||||
| ------------- | -------------- | -------------- | -------------- | ----- |
|
||||
| 类型安全 | ✅ compile-time | ✅ compile-time | ⚠️ runtime | ❌ 运行时 |
|
||||
| 单个可选 | ✅ 可用 | ✅(更简洁) | N/A | N/A |
|
||||
| 多值互斥 | ✅ 核心用途 | ❌ | N/A | N/A |
|
||||
| 动态类型 | ❌ | ❌ | ✅ | ✅ |
|
||||
| JSON 互转 | ⚠️ 需额外处理 | ✅ | ✅ | ✅ |
|
||||
| wire overhead | 低 | 低 | 中(需存 type_url) | 低 |
|
||||
|
||||
## 关联笔记
|
||||
|
||||
|
||||
Reference in New Issue
Block a user