第1章 新时代的语言

从Rust缘起、内存安全、零成本抽象和实用主义出发,追踪源码到产物的执行链,并建立采用Rust的工程判断。

从系统语言的两难开始

传统系统语言给程序员直接内存控制,却把悬垂指针、重复释放和数据竞争留到运行期;托管语言用运行时回收降低内存管理负担,却引入停顿、对象布局和资源释放时序方面的约束。Rust缘起于一个更具体的问题:能否让编译器验证资源访问规则,同时保留原生代码的布局和性能控制?是可检查条件,不是“程序不会崩溃”的泛称。

设计哲学一:内存安全前移到编译期

所有权把释放责任绑定到值,借用把临时访问变成受约束的引用,生命周期描述引用不能越过被引用值。编译器拒绝无法证明安全的路径,开发者再通过重新设计owner、缩短借用、复制小值或在明确契约下使用unsafe解决。提高的是失败确定性:同一源码在部署前就暴露问题。

fn first_word(text: &str) -> &str {
    text.split_whitespace().next().unwrap_or("")
}
 
let owned = String::from("safe systems");
let word = first_word(&owned);
assert_eq!(word, "safe");

返回引用与输入关联,局部owned活着时才可使用word。这不证明分词符合所有语言规则,却证明引用不会指向已释放的String缓冲区。

设计哲学二:零成本抽象

通过泛型单态化、内联、枚举布局优化和迭代器融合落地。它不是“所有抽象都零指令”:分配、动态分派、引用计数和边界检查仍有成本;关键是成本可见,并且高层表达不会被迫引入不需要的运行时。

let total: i64 = (0..1_000)
    .map(|n| n * 2)
    .filter(|n| n % 3 == 0)
    .sum();
 
assert_eq!(total, 333_666);

验证零成本不能只看源码,应在release profile比较基准和汇编,并确认没有把I/O、allocator噪声或debug优化级别混入结论。

设计哲学三:实用主义

Rust没有追求纯粹的单一范式。它同时提供表达式、可变绑定、结构体、枚举、Trait、闭包、迭代器、线程、async和unsafe。意味着可以在安全外壳中保留很小的unsafe核心,也可以在并行计算中用Rayon而非手写调度器。

Rust的编译和执行

cargo run看似一步,实际包含依赖解析、crate graph构建、宏展开、名称解析、类型检查、借用检查、MIR优化、LLVM代码生成、链接与进程启动。帮助判断错误归属:过程宏panic发生在编译期,undefined reference发生在链接期,文件不存在发生在运行期。

fn main() {
    println!("target={} profile=release? {}", std::env::consts::ARCH, !cfg!(debug_assertions));
}

语言现状、未来与采用判断

语言现状与未来应从edition、稳定发布、目标平台、核心库、包生态和团队能力判断,而不是从热度推断。至少记录rustc -Vvcargo -V、target、profile、lockfile和feature。采用Rust的收益通常在长寿命系统组件、并发服务、CLI和安全边界上明显;原型、生态强依赖或团队没有维护能力时,也可能不是当前最优解。

本章回顾

Rust以编译期证明换取更早失败,以零成本抽象保留系统性能,以实用主义连接生态与外部代码。判断Rust程序必须区分编译、链接和运行阶段,并保存toolchain provenance。语言选择最终服务于明确的资源、并发、互操作和维护约束。

术语表

讨论

评论区加载中…