Corrode 这篇《Migrating from Go to Rust》,最值得看的地方,不是“Rust 又来挑战 Go”。
反而是它没有急着踩 Go。作者承认,Go 在后端仍然很强:静态二进制、网络标准库、gRPC、数据库生态、工具链,都成熟。大多数服务用 Go 写,够快,够稳,也够便宜。
真正的反常点在另一处:这篇指南关心的不是 benchmark,而是生产里的 nil panic、数据竞争、错误上下文丢失、P99 延迟尾部。这些问题到底该靠人记住,还是靠语言不让你忘。
Go 和 Rust 的分水岭,不在跑分
作者 Matthias Endler 先把立场摊开:他不喜欢 Go,认为 Go 把“容易”误当成“简单”;他也经营 Rust 咨询业务,Rust 被更多团队采用,对他有利。
这点要先放在桌面上。它不是中立白皮书,是一份带立场的迁移建议。但披露偏见,比伪装客观干净。
两门语言真正的分歧,不是“谁更先进”。而是风险放在哪里。
| 问题 | Go 常见做法 | Rust 常见做法 | 现实差异 |
|---|---|---|---|
| 空值 | nil 检查、lint、团队约定 | Option<T> 强制处理 None | Go 靠人别漏,Rust 让漏处理更难通过编译 |
| 错误 | if err != nil、手动包装上下文 | Result<T, E>、?、匹配 | Go 简洁直接,但错误语义容易散;Rust 更啰嗦,也更显式 |
| 数据竞争 | -race 运行时检测,依赖测试覆盖 | Send/Sync 编译期约束 | -race 有用,但没跑到的路径发现不了 |
| 资源生命周期 | GC 和约定兜底 | 所有权、借用、RAII | Go 开发顺,Rust 前期卡,但生命周期更早暴露 |
| 延迟尾部 | GC 已经很强,但仍有分配和暂停成本 | 无 GC,热路径可控 | Rust 不必然更快,但在高分配和 P99 敏感场景更有优势 |
这张表不能读成 Rust 全面碾压 Go。那是偷懒。
Go 的成功,恰恰来自它把复杂度压低。上手快,部署轻,工具链统一,团队协作成本低。Rob Pike 说过,gofmt 的风格不是任何人的最爱,却是所有人的最爱。意思很朴素:别把时间浪费在无谓争论上。
Go 和 Rust 都相信工具链。区别是,Go 主要用工具链减少协作摩擦;Rust 还试图用类型系统减少事故入口。
受影响的不是语言粉丝,是维护长期服务的人
这篇指南最该被谁看?不是想吵 Go 和 Rust 谁赢的人。
第一类,是正在维护 Go 后端服务、已经被线上稳定性问题磨过的工程团队。你们要做的不是把服务一夜之间改成 Rust,而是先盘点事故类型:nil panic 多不多,错误上下文是不是经常丢,并发共享状态是不是靠口头纪律,P99 延迟是不是被分配和 GC 放大。
如果这些问题很少,迁移收益就未必覆盖成本。继续用 Go,把 lint、errcheck、staticcheck、nilaway、-race、context 规范补齐,可能更划算。
如果这些问题反复出现,Rust 才开始有现实意义。它不是魔法,是把一部分线上排雷,改成编译期付款。
第二类,是技术负责人。你要关心的不是“Rust 工程师酷不酷”,而是账怎么结。
| 决策问题 | 更偏向继续 Go | 更偏向评估 Rust |
|---|---|---|
| 服务类型 | CRUD、内部 API、普通网络服务 | 高并发核心链路、基础设施组件、延迟敏感服务 |
| 团队现状 | Go 熟练,事故少,交付压力大 | 线上 bug 成本高,长期维护压力重 |
| 风险来源 | 业务变化快,性能不是瓶颈 | 并发安全、资源控制、错误模型经常出问题 |
| 迁移方式 | 强化工具和规范 | 从边界模块、性能热点、可靠性要求高的组件试点 |
| 最大代价 | 继续依赖纪律 | 学习曲线、编译时间、异步心智负担、招聘成本 |
这里的关键词是“试点”,不是“重写”。
如果一个团队连错误类型、超时策略、日志上下文都没有统一,直接迁 Rust 很可能只是把混乱换一种语法。Rust 会放大工程纪律,也会暴露组织问题。编译器能拦住很多 bug,拦不住需求乱飞、边界不清和抽象失控。
迁移值不值,看你愿不愿用学习成本换确定性
我不太买账“Rust 适合所有后端”的说法。很多服务用 Go 就很好。招人更容易,编译更快,生态更熟,排障资料也多。
但我也不买账“Go 已经足够,所以 Rust 没必要”。这话只对一部分团队成立。
问题不在语言信仰,而在事故价格。
一个 nil 在罕见路径触发 panic,单看代码只是少了一行判断。放到生产里,可能就是一次半夜告警。一个 map 被两个 goroutine 改写,测试没覆盖到,流量一上来才炸。一个错误被 return,却没带上下文,排障只能靠猜。
Go 不是没有办法。-race 很有价值,不能轻飘飘说它没用。它的问题是运行时检测,只能发现被执行过的路径。lint 和规范也有用,但前提是团队持续执行。
Rust 的态度更硬:Option 没处理,别当值用;Result 没处理,别装没事;跨线程共享可变状态,先过 Send/Sync。你可以嫌它烦,但它确实把一批事故提前变成编译错误。
延迟也是同一逻辑。Go 的 GC 已经很强,低暂停、并发、足够适合常见服务。Rust 无 GC 不等于天然更快。它的优势更具体:高分配压力、热路径控制、P99 尾延迟敏感时,Rust 更容易把不确定性压下去。
这里有一点历史回声。早年的铁路、电力、报业,扩张到一定规模后,真正的竞争不再只是“谁铺得快”,而是谁能把标准、调度、维护和事故责任固定下来。技术系统越大,纪律越贵。
Go 的纪律成本低,所以它赢了很多后端场景。Rust 的纪律成本前置,所以它适合那些不想把错误留到凌晨两点再结算的地方。
接下来最该观察的变量,不是又有多少团队宣布“全面拥抱 Rust”。那种口号没多少信息量。
更该看三件事:
- Go 团队的事故复盘里,nil、数据竞争、错误上下文、尾延迟是否反复出现;
- Rust 试点是不是能落在清晰边界上,而不是把整个系统推倒重来;
- 团队能不能承担 Rust 的学习曲线、编译等待、异步复杂度和招聘成本。
“天下熙熙,皆为利来。”技术迁移也一样。Rust 给的利,不是漂亮跑分,而是更高的确定性。只是这笔利,不会免费到账。
