m06-error-handling
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseError Handling
错误处理
Layer 1: Language Mechanics
第一层:语言机制
Core Question
核心问题
Is this failure expected or a bug?
Before choosing error handling strategy:
- Can this fail in normal operation?
- Who should handle this failure?
- What context does the caller need?
这个故障是预期内的还是一个bug?
在选择错误处理策略之前:
- 正常运行时是否可能发生该故障?
- 谁应该处理这个故障?
- 调用者需要哪些上下文信息?
Error → Design Question
错误 → 设计问题
| Pattern | Don't Just Say | Ask Instead |
|---|---|---|
| unwrap panics | "Use ?" | Is None/Err actually possible here? |
| Type mismatch on ? | "Use anyhow" | Are error types designed correctly? |
| Lost error context | "Add .context()" | What does the caller need to know? |
| Too many error variants | "Use Box<dyn Error>" | Is error granularity right? |
| 模式 | 不要只说 | 而是要问 |
|---|---|---|
| unwrap会触发panic | "使用?" | 这里真的可能出现None/Err吗? |
| ?运算符出现类型不匹配 | "使用anyhow" | 错误类型的设计是否正确? |
| 丢失错误上下文 | "添加.context()" | 调用者需要知道哪些信息? |
| 错误变体过多 | "使用Box<dyn Error>" | 错误的粒度是否合适? |
Thinking Prompt
思考提示
Before handling an error:
-
What kind of failure is this?
- Expected → Result<T, E>
- Absence normal → Option<T>
- Bug/invariant → panic!
- Unrecoverable → panic!
-
Who handles this?
- Caller → propagate with ?
- Current function → match/if-let
- User → friendly error message
- Programmer → panic with message
-
What context is needed?
- Type of error → thiserror variants
- Call chain → anyhow::Context
- Debug info → anyhow or tracing
处理错误前:
-
这属于哪种类型的故障?
- 预期内 → Result<T, E>
- 正常的缺失情况 → Option<T>
- Bug/违反不变量 → panic!
- 不可恢复 → panic!
-
谁来处理它?
- 调用者 → 使用?传播
- 当前函数 → match/if-let
- 用户 → 友好的错误消息
- 程序员 → 带消息的panic
-
需要哪些上下文?
- 错误类型 → thiserror变体
- 调用链 → anyhow::Context
- 调试信息 → anyhow或tracing
Trace Up ↑
向上追溯 ↑
When error strategy is unclear:
"Should I return Result or Option?"
↑ Ask: Is absence/failure normal or exceptional?
↑ Check: m09-domain (what does domain say?)
↑ Check: domain-* (error handling requirements)| Situation | Trace To | Question |
|---|---|---|
| Too many unwraps | m09-domain | Is the data model right? |
| Error context design | m13-domain-error | What recovery is needed? |
| Library vs app errors | m11-ecosystem | Who are the consumers? |
当错误策略不明确时:
"我应该返回Result还是Option?"
↑ 询问:这种缺失/故障是正常情况还是异常情况?
↑ 查看:m09-domain(领域的要求是什么?)
↑ 查看:domain-*(错误处理的要求)| 场景 | 追溯到 | 问题 |
|---|---|---|
| unwrap过多 | m09-domain | 数据模型是否正确? |
| 错误上下文设计 | m13-domain-error | 需要什么样的恢复机制? |
| 库与应用的错误对比 | m11-ecosystem | 使用者是谁? |
Trace Down ↓
向下落实 ↓
From design to implementation:
"Expected failure, library code"
↓ Use: thiserror for typed errors
"Expected failure, application code"
↓ Use: anyhow for ergonomic errors
"Absence is normal (find, get, lookup)"
↓ Use: Option<T>
"Bug or invariant violation"
↓ Use: panic!, assert!, unreachable!
"Need to propagate with context"
↓ Use: .context("what was happening")从设计到实现:
"预期内故障,库代码"
↓ 使用:thiserror实现类型化错误
"预期内故障,应用程序代码"
↓ 使用:anyhow实现便捷的错误处理
"正常的缺失情况(查找、获取)"
↓ 使用:Option<T>
"Bug或违反不变量"
↓ 使用:panic!、assert!、unreachable!
"需要携带上下文传播错误"
↓ 使用:.context("当时正在执行的操作")Quick Reference
快速参考
| Pattern | When | Example |
|---|---|---|
| Recoverable error | |
| Absence is normal | |
| Propagate error | |
| Dev/test only | |
| Invariant holds | |
| Unrecoverable | |
| 模式 | 使用场景 | 示例 |
|---|---|---|
| 可恢复错误 | |
| 正常的缺失情况 | |
| 传播错误 | |
| 仅开发/测试环境 | |
| 不变量成立时 | |
| 不可恢复 | |
Library vs Application
库 vs 应用程序
| Context | Error Crate | Why |
|---|---|---|
| Library | | Typed errors for consumers |
| Application | | Ergonomic error handling |
| Mixed | Both | thiserror at boundaries, anyhow internally |
| 上下文 | 错误库 | 原因 |
|---|---|---|
| 库 | | 为使用者提供类型化错误 |
| 应用程序 | | 便捷的错误处理体验 |
| 混合场景 | 两者都用 | 边界处用thiserror,内部用anyhow |
Decision Flowchart
决策流程图
Is failure expected?
├─ Yes → Is absence the only "failure"?
│ ├─ Yes → Option<T>
│ └─ No → Result<T, E>
│ ├─ Library → thiserror
│ └─ Application → anyhow
└─ No → Is it a bug?
├─ Yes → panic!, assert!
└─ No → Consider if really unrecoverable
Use ? → Need context?
├─ Yes → .context("message")
└─ No → Plain ?故障是预期内的吗?
├─ 是 → 唯一的“故障”是缺失吗?
│ ├─ 是 → Option<T>
│ └─ 否 → Result<T, E>
│ ├─ 库 → thiserror
│ └─ 应用程序 → anyhow
└─ 否 → 这是一个bug吗?
├─ 是 → panic!、assert!
└─ 否 → 考虑是否真的不可恢复
使用? → 需要上下文吗?
├─ 是 → .context("消息")
└─ 否 → 直接使用?Common Errors
常见错误
| Error | Cause | Fix |
|---|---|---|
| Unhandled None/Err | Use |
| Type mismatch | Different error types | Use |
| Lost context | | Add |
| Missing Result return | Return |
| 错误 | 原因 | 修复方案 |
|---|---|---|
| 未处理的None/Err | 使用 |
| 类型不匹配 | 错误类型不同 | 使用 |
| 丢失上下文 | 未携带上下文的? | 添加 |
| 返回类型不是Result | 返回 |
Anti-Patterns
反模式
| Anti-Pattern | Why Bad | Better |
|---|---|---|
| Panics in production | |
| Ignore errors silently | Bugs hidden | Handle or propagate |
| Bad UX, no recovery | Result |
| Box<dyn Error> everywhere | Lost type info | thiserror |
| 反模式 | 危害 | 更好的做法 |
|---|---|---|
到处使用 | 生产环境中触发panic | 使用 |
| 静默忽略错误 | 隐藏bug | 处理或传播错误 |
对预期内错误使用 | 糟糕的用户体验,无法恢复 | 使用Result |
到处使用 | 丢失类型信息 | 使用thiserror |
Related Skills
相关技能
| When | See |
|---|---|
| Domain error strategy | m13-domain-error |
| Crate boundaries | m11-ecosystem |
| Type-safe errors | m05-type-driven |
| Mental models | m14-mental-model |
| 场景 | 查看 |
|---|---|
| 领域错误策略 | m13-domain-error |
| 库边界 | m11-ecosystem |
| 类型安全错误 | m05-type-driven |
| 心智模型 | m14-mental-model |