C 里用 goto 做错误处理,其实很体面
来源:thestateofinahaze.net — 2026-10-25
📋 概述
作者从 Go 和 Zig 回到 C,最不适应的就是错误处理没有 defer 与 errdefer 兜底。他先展示 Go 的 defer 加 errors.Wrap 有多省事,再展示 Zig 在手动内存管理下用 errdefer 按序回收、并配合「先预留」模式在分配全部完成后写 errdefer comptime unreachable。然后在 C 里,他最初为每次失败写嵌套的清理循环,越写越丑,还因为一个小于等于写错下标而容易出错。转折点是读 John Carmack 关于内联代码的邮件,让他意识到可以用 goto 把清理代码集中成一条线性路径。
🔑 核心要点
- 先给出理想态:Go 里锁内失败只要 errors.Wrap 后返回,defer 负责解锁
- Zig 更接近 C 的处境:errdefer 让回收按逆序自动执行,不必手工追踪哪些已分配
- 一个实用技巧:所有分配完成后写 errdefer comptime unreachable,把后续代码的隐式错误源封住
- 朴素写法的痛点很具体:每个失败点都要写一遍清理循环,且容易把小于写成小于等于
- 转折来自 John Carmack 关于内联代码的邮件:与其层层嵌套,不如让失败路径线性汇合
- 结论是反直觉的:goto 用在错误处理上并不脏,它把清理变成一处而不是 N 处
💡 金句
It is Friday after all, so I'll offer this little glimpse as an example from what I do at work…
👍 0
👎 0
← 返回 Lobsters 首页