有经验开发者的Rust:是什么让它与众不同

Rust在编程语言中取得了一些不寻常的成就:它在性能关键型系统(操作系统、嵌入式系统、浏览器、数据库)中有高采用率,同时也因防止整类bug的正确性保证而受到赞赏。对于来自C++、Go或Python的有经验开发者,以下是Rust真正不同的地方以及这些差异为什么重要。

所有权系统

Rust的定义性特征:一个编译时所有权系统,使内存管理明确而不需要垃圾回收器。三条规则:1)每个值只有一个所有者。2)当所有者离开作用域时,值被丢弃(内存被释放)。3)在同一时间,对一个值可以有一个可变引用或任意数量的不可变引用(但不能同时有两者)。为什么这些规则重要:它们在编译时消除了整类内存bug——释放后使用、双重释放、悬空指针以及并发代码中的数据竞争。这些bug约占C和C++代码库中CVE(安全漏洞)的70%(微软和谷歌Project Zero引用的数据)。借用检查器:编译器执行所有权规则。如果你的代码违反了这些规则,它就不会编译。这就是著名的”与借用检查器斗争”体验——编译器是正确的,但理解你的直觉为什么错了需要时间。借用检查器捕获的内容:移入函数的字符串在调用后不能使用;引用的生命周期不能超过它引用的值;不能同时对同一个值有可变引用和不可变引用。成本:Rust代码最初通常需要更长时间编写,因为编译器拒绝在其他语言中会是运行时错误的模式。回报:一旦编译通过,保证大类bug不存在。有经验的Rust开发者将这描述为”写得慢但发布得快”。

Rust没有的东西(设计上)

没有null:Rust没有空指针。取而代之:`Option`,它要么是`Some(value)`要么是`None`。你被迫处理两种情况——`None`不能意外地被用作值。这完全消除了”空指针异常”类别的bug。没有异常:Rust对可恢复错误使用`Result`(要么`Ok(value)`要么`Err(error)`),对不可恢复错误使用`panic!`(它展开堆栈,类似于异常)。每个可能失败的函数都必须返回`Result`;每个调用者都必须明确处理错误情况。`?`操作符惯用地向上传播错误:`let value = may_fail()?;`如果`may_fail()`返回`Err`则提前返回错误。这使代码中的错误路径明确,与可以无形传播的异常不同。没有垃圾回收器:Rust的所有权系统确定性地处理内存,不需要GC。这给出可预测的延迟(无GC暂停)、更低的内存开销,以及在GC不可能的环境中嵌入Rust的能力(内核、嵌入式系统)。没有数据竞争:应用于并发代码的所有权规则使数据竞争不可能。如果两个线程可能访问相同的数据,其中一个必须有独占的可变访问(通过Mutex)或两者都必须有不可变访问。编译器执行这一点。

生态系统和何时使用Rust

标准库:比Python或Java更小——设计上如此。在其他语言中是标准库的许多东西在Rust中是crate(如正则表达式、HTTP客户端、序列化)。Cargo(Rust的包管理器):被广泛认为是任何系统语言中最好的包管理器——依赖解析、构建配置、测试、文档、基准测试,全部通过`cargo`。Crates.io:包注册表——约130,000个crate(2025年)。关键crate:Tokio(异步运行时——几乎普遍用于异步I/O);Serde(序列化/反序列化——几乎用于每个读取或写入结构化数据的Rust项目);Rayon(数据并行性——轻松并行化迭代器);Axum或Actix-web(Web框架);SQLx(带编译时查询检查的异步SQL)。Rust是正确选择的情况:性能和内存至关重要的系统编程;之前使用C或C++并且你想要内存安全的任何地方;较大系统的性能关键部分(通过PyO3的Python绑定);WebAssembly编译(Rust拥有最好的WASM工具链);嵌入式系统编程。可能不适合的情况:Go或Python可以更快编写的Web应用程序后端;脚本和自动化;开发速度是主要考量且不需要这种级别正确性的项目。

上一篇 Rust for Experienced Developers: What Makes It Different
下一篇 Greek Islands Beyond Santorini: Where to Actually Go