请点击上方蓝字TonyBai订阅公众号!
大家好,我是Tony Bai。
近年来,Rust 语言无疑是技术圈最炙手可热的明星。它以“内存安全”的核心承诺,向统治了系统编程领域数十年的 C++ 发起了强有力的挑战。无数文章和布道者都在宣扬一个近乎“神话”的观点:用 Rust,你就能告别段错误和内存泄漏。
然而,就在这股“Rust 替换一切”的热潮中,一个来自行业核心的声音,给我带来了深深的思考。
Moritz Sichert,高性能数据库 CedarDB 的联合创始人兼 CEO,最近发表了一个“反直觉”的观点:
“Rust 是一门很棒的语言,我真的很喜欢用它。然而,当涉及到数据库系统时,我仍然会选择 C++ 而不是 Rust。”
一个数据库 CEO,在一个对数据安全和系统稳定性要求极致的领域,放弃了以“安全”著称的 Rust,转而拥抱充满了“历史遗留问题”的 C++。这究竟是为什么?
这并非一次简单的“厚此薄彼”,而是一场关于工程现实与语言哲学之间深刻权衡的精彩案例。
理论安全 vs 工程现实:unsafe
的“逃生舱口”
Moritz 首先承认了 Rust 的优点:理论上,Rust 通过其所有权系统和借用检查器,提供了远超 C++ 的默认安全性。这正是大家喜爱 Rust 的原因。
但问题在于,像 CedarDB 这样的高性能数据库,其开发工作远不止是处理业务逻辑。它需要深入到硬件的毛细血管中,榨干每一滴性能。这意味着:
使用大量底层的 CPU 特性。
实现复杂的侵入式数据结构。
进行带有验证的、乐观且激进的内存访问。
在这些场景下,Rust 的安全检查反而成了“束缚”。为了完成任务,你必须使用 Rust 提供的“逃生舱口”——unsafe
关键字。
而 Moritz 抛出的重磅炸弹正在于此:
“一旦你在 Rust 中写下
unsafe
代码,所有的赌注都将失效。在unsafe
代码中,你遇到未定义行为(UB, Undefined Bahavior)的风险,甚至比在 C++ 中还要高。”
unsafe
Rust:一个更危险的“黑暗森林”?
这个论断足以颠覆许多人的认知。unsafe
Rust 怎么会比 C++ 还危险?
关键在于理解 unsafe
到底意味着什么。它不是简单地“关闭”安全检查,而是程序员向编译器立下了一个契约:“编译器,请相信我,接下来的这段代码,我将手动保证它完全遵守 Rust 的内存模型和别名规则(Aliasing Rules)。”
这正是问题的核心所在。
C++ 的危险是“已知的”:C++ 就像一片广阔的雷区,但经过几十年的探索,老兵们已经绘制出了详细的“排雷图”。虽然处处是坑,但如何避免、如何调试,已经积累了大量的工程实践和模式。
unsafe
Rust 的危险是“微妙的”:unsafe
区域就像一个“黑暗森林”,你不仅要面对 C++ 程序员熟悉的裸指针、内存布局等问题,更要命的是,你还必须手动维护 Rust 那套比 C++ 更为严格的别名规则(例如,在任何给定时间,你只能有一个可变引用&mut T
,或者任意数量的不可变引用&T
,但不能两者都有)。
对于一位经验丰富的 C++ 开发者而言,在 unsafe
块里很容易不自觉地写出 C++ 风格的指针操作,却无意中违反了 Rust 的核心不变量,从而触发 UB。这种“新规则”下的自由,反而成了一个更容易跌落的陷阱。
Moritz 的观点是:在一个必须大量使用 unsafe
的项目中,与其在一个受严格规则约束的环境里“戴着镣铐跳舞”,不如直接选择那个虽然危险、但规则更为人熟知且自由度更高的 C++。
聊聊 Go:一种不同的安全哲学
那么,聊了这么多 Rust 和 C++,我们作为 Gopher 能从中得到什么启发呢?这恰好能让我们更深刻地理解 Go 的设计取舍。
Go 语言同样有一个 unsafe
包。但与 Rust 的设计哲学截然不同。
Rust 的 unsafe
是语言的一等公民,是其系统编程能力的重要组成部分,是为了实现“零成本抽象”而设计的必要工具。
而 Go 的 unsafe
,从其文档的第一句话起,就在极力地“劝退”你:
“任何使用了 unsafe 包的程序都可能在未来 Go 语言版本中无法移植……使用 unsafe 的代码,其安全性需要程序员手动保证,我们不建议使用。”
在 Go 的世界里,unsafe
更像一个被严格限制的“后门”,而非一个功能特性。它的存在主要是为了实现标准库(如 runtime
、sync
),或在极少数与 C 库交互、进行极致性能微调的场景下使用。
我们可以这样总结三者的哲学:
C++:默认给予你全部的权力与危险,安全是你的责任。
Rust:默认提供极致的安全,但给你一个
unsafe
的选项,让你在立下严格契约为前提下重获权力。Go:默认通过 GC 和简单的内存模型提供高度的工程安全与效率,
unsafe
是一个官方不鼓励、非标准的“应急方案”。
Go 的选择是,在绝大多数场景下,宁愿牺牲掉那部分通过复杂手动内存管理换来的极限性能,也要保证语言模型的简单性和大规模团队协作的工程效率与安全。
小结:没有神话,只有权衡
Moritz Sichert 的观点,并非是对 Rust 的全盘否定,更不是在鼓吹 C++ 的回归。
它有力地击碎了“Rust=绝对安全”的技术神话,揭示了一个冰冷的工程现实:在任何复杂的系统中,安全都是一个连续的光谱,而不是一个二元的开关。
当你的业务场景把你推向性能金字塔的顶尖,逼迫你大量使用 unsafe
时,Rust 的安全优势就会被削弱,其复杂的底层规则甚至可能成为新的风险来源。
这个案例告诉我们,技术选型永远没有“银弹”,只有基于特定问题、特定团队、特定目标的深刻权衡。作为开发者,我们最重要的能力,就是理解自己手中工具的设计哲学、优势边界以及它为之付出的代价。
对于绝大多数的后端服务、云原生应用而言,Go 和 Rust 提供的现代安全模型无疑是巨大的进步。但请记住,当有人在讨论“是否选择 C++”时,他可能不是在开历史的倒车,而是在思考一个我们尚未触及的、更深层次的工程问题。
如果本文对你有所帮助,请帮忙点赞、推荐和转发!
点击下面标题,阅读更多干货!
- Go vs. Rust再掀波澜:Grab真实案例复盘,Gopher如何看待这场“效率与代价”之争?
- 百万行依赖的“恐惧”:一位Rust开发者的深度反思与Go的启示
- InfluxDB 3.0 GA:四年Rust重构,是新生还是挑战?
🔥 你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?
想写出更地道、更健壮的Go代码,却总在细节上踩坑?
渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
想打造生产级的Go服务,却在工程化实践中屡屡受挫?
继《Go语言第一课》后,我的 《Go语言进阶课》 终于在极客时间与大家见面了!
我的全新极客时间专栏 《Tony Bai·Go语言进阶课》 就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。
目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!