Error Handling: Exceptions Over Status Codes
# 错误处理方式比较:异常 vs 状态码
错误处理在不同语言中有不同策略。

- **JavaScript** 和 **Python** 通常使用 **抛出异常**
- **Rust** 通过 `Result` 类型变相实现异常处理
- **C** 和 **Go** 语言通常 **返回错误值**,需要主动判断是否为 `-1` 或空值
我一直想知道,哪一种方式更好?
前不久,我读到一篇多年前的 [文章](https://nedbatchelder.com/text/exceptions-vs-status.html),作者 Ned Batchelder 明确提出:
**抛出异常好于返回状态码**。
他的观点很有说服力。文章似乎没有中译,我将其整理翻译如下。
---
## 异常与状态码
**作者**:Ned Batchelder
**原文地址**:[nedbatchelder.com](https://nedbatchelder.com/text/exceptions-vs-status.html)
在软件开发中,错误处理主要有两种方式:
1. **抛出异常 (throwing exceptions)**
2. **返回状态码 (returning status codes)**
多数人认可异常更好,但仍有开发者偏爱状态码。下面解释为什么异常是更优的选择。
---
## 1. 代码更干净
异常让你省去大量显式的错误检查过程,它会**自动沿调用栈向上传递**,直到被捕获。
因此,你的大部分代码不必插入重复的错误检查逻辑,从而更加简洁可读。
**状态码写法:**
STATUS DoSomething(int a, int b)
{
STATUS st;
st = DoThing1(a);
if (st != SGOOD) return st;
st = DoThing2(b);
if (st != SGOOD) return st;
return SGOOD;
}
必须在每一步后判断返回值是否正常,才能继续。
**异常写法:**
void DoSomething(int a, int b)
{
DoThing1(a);
DoThing2(b);
}
**总结**:
在复杂场景下,状态码带来的噪音会成倍增加;异常则保持核心逻辑更清晰。
---
## 2. 保留有意义的返回值
- 状态码**占用返回值位置**,迫使你增加额外检查逻辑
- 某些函数原本仅需返回正常值,现在要额外处理异常值(如返回 `NULL` 或 `-1`)
长期来看:
- 代码量增多
- 返回值规则变复杂
- 每个调用方都必须同步更新错误判断逻辑
**异常优势**:
- 函数只在成功时返回正常值
- 错误处理集中在一个地方
---
## 3. 携带更多错误信息
- 状态码往往是简单整数,信息量有限
- 如果错误是“找不到文件”,状态码无法告知**是哪一个文件**
- 必须依赖独立日志来补充信息
异常是类实例,可以:
- 携带**具体数据**
- 使用子类区分多种错误类型
- 构建丰富的错误信息体系
---
## 4. 适用于无法返回值的函数
例如:
- **构造函数**没有显式返回值,难以用状态码返回错误
- **析构函数**等隐式调用函数,更无法返回状态码
若不用异常:
- 只能发明绕路机制传递错误
- 或假装这些函数永远不会失败(风险极大)
随着代码规模增长,失败概率升高,不暴露错误只会让系统更不可预测。
---
## 5. 错误可见性
如果**状态码**未被检查:
- 错误会被**静默吞掉**
- 代码继续执行,问题可能在下游才爆发,难以回溯
**异常**若未捕获:
- 会沿调用栈冒泡
- 最终可能由顶层捕获并交给 OS 显示错误
- 虽然对程序不是最优体验,但**至少错误是可见的**,可定位到抛出位置
**总结**:
- 状态码更易隐藏问题
- 异常让错误暴露出来
---
## 6. 反对意见及回应
著名程序员 **Joel Spolsky** 对异常的批评:
> - 异常是“不可见的 goto”,阅读代码时看不到哪些地方会抛异常
> - 异常造成函数有太多可能的退出路径
> - 要写正确代码,必须考虑每条路径
> - 调用可能抛异常的函数时,若不立即捕获,控制流可能出现意外中断
**回应**:
- 采用状态码则必须**显式检查每个返回值**
- 你只是从**隐式复杂性**转为**显式复杂性**
- 显式复杂性会淹没主要逻辑,使代码更杂乱、更难维护
- 程序员常用自定义机制**隐藏显式错误处理**,这会退化成隐式处理,且比 `try` 不方便、不灵活
- 更糟的是,开发者可能**直接忽略错误处理**,埋下隐患
---
## 7. 结论
状态码:
- 笨重、易被忽略
- 占据返回值
- 在特定场景下不适用
异常:
- 信息丰富
- 控制流简洁
- 不易被悄然忽视
**如果语言支持异常,建议优先使用它们。**
---
> **相关延伸**
> 现代跨平台 AI 内容创作工具(如 [AiToEarn 官网](https://aitoearn.ai/))在设计中,也依赖清晰的错误处理策略。
> 这些系统集成 AI 生成、跨平台发布、分析与模型排名,用于在抖音、快手、微信公众号、B 站、小红书、Facebook、Instagram、LinkedIn、Threads、YouTube、Pinterest 和 X(Twitter)等平台高效分发内容。
> 无论是软件工程还是 AI 工具,**让错误及时可见并妥善处理**,始终是构建健壮系统的关键。