Rust —— 为什么整个工具圈都在用它重写一遍
普通课约 40 分钟
本课导读
你大概率是这样撞见 Rust 的:某个工具的介绍页写着 "blazingly fast, written in Rust",评论区一片欢呼,而你不知道大家在欢呼什么。本课回答三个问题:Rust 是什么、它解决了什么别人解决不了的痛、为什么突然到处都是它。学完你能看懂"用 Rust 重写"这句话背后的全部潜台词——顺便剧透:你天天用的 Next.js 里面就藏着 Rust。预计 40 分钟。
说明
这个 Track 的代码块不在浏览器里运行(Rust 需要本地编译器),点右上角可复制,部分代码块附有折叠的「本地运行指引」。但本课目标是看懂,不要求你装环境。
先定位:Rust 在语言地图上的位置
你已经接触过两门语言,先拿它们当坐标系:
| Python / JavaScript | TypeScript | Rust | |
|---|---|---|---|
| 类型检查 | 无(运行时才暴雷) | 编译前检查,运行时类型被擦除 | 编译期检查,类型决定内存布局 |
| 执行方式 | 解释/即时编译,跑在引擎上 | 转译成 JS 再跑 | 直接编译成机器码,不需要引擎 |
| 内存管理 | 垃圾回收器(GC)自动打扫 | 同 JS | 没有 GC,编译器推算 |
| 典型速度 | 慢~中 | 同 JS | 和 C/C++ 一个量级 |
两个关键词先解释清楚:
- 编译成机器码:Python 和 JS 运行时需要一个"引擎"(解释器)现场翻译代码;Rust 在你开发机上就把代码翻译成 CPU 直接执行的指令,发布出去的是一个独立的可执行文件——没有引擎、没有依赖、启动即满速。这是它快的第一个原因。
- 没有 GC:这是 Rust 最独特的地方,也是它存在的理由,下面单独讲。
核心痛点:内存管理的"三难困境"
程序运行时要不断申请内存(存变量、数组、对象),用完要归还。谁来负责归还?历史上只有两条路,各有致命伤:
路线一:程序员手动管(C / C++)。性能极致,但人会犯错:忘了归还是内存泄漏;归还后又去用是 use-after-free——后者是安全漏洞的头号来源。微软和 Chrome 团队都统计过:约 70% 的严重安全漏洞是内存错误。
路线二:垃圾回收器自动管(Python / JS / Java / Go)。运行时有个"清洁工"线程定期扫描哪些内存没人用了、回收掉。安全省心,但代价是:清洁工本身消耗 CPU 和内存,而且它开工时程序可能要暂停(GC pause)。写网页无所谓,写游戏引擎、数据库、浏览器就不能忍。
提示
类比:手动管理像自己记账的现金交易——高效但记错一笔就出大事;GC 像雇了个管家——省心但要付工资,管家盘点时全家还得配合暂停。四十年来大家默认:要么快但危险,要么安全但有开销,二选一。
Rust 的第三条路:所有权(Ownership)。核心思想是——归还内存的时机,其实在编译的时候就能推算出来,根本不用等到运行时再派清洁工去扫。Rust 给每个值规定一个唯一的所有者(某个变量),所有者离开作用域,值立刻自动释放;编译器全程追踪所有权的转移,任何可能"用了已释放内存"的写法直接编译不通过。
结果:C 的性能 + GC 语言的安全,运行时零开销——代价全部预付在编译期和你的学习曲线上。
30 秒体验所有权:一段编译不过的代码
不用懂语法细节,感受一下"编译器管得有多宽":
fn main() { let s1 = String::from("hello"); // s1 是这个字符串的所有者 let s2 = s1; // 所有权转移(move)给了 s2 // 从这行起 s1 已经"作废" println!("{}", s2); // OK println!("{}", s1); // 编译错误!value borrowed here after move }
本地运行指引
1. 安装 Rust 工具链(官方一键脚本):https://rustup.rs 2. 新建项目:cargo new hello && cd hello 3. 把代码粘进 src/main.rs 4. 运行:cargo run —— 你会看到编译器拒绝编译,并画出箭头解释所有权在哪一行转移了
在 JS 里 const s2 = s1 之后两个变量随便用;在 Rust 里赋值意味着所有权移交,旧变量立刻失效。第一次见会觉得莫名其妙,但正是这套规则让编译器能在编译期证明"绝不会有两个地方同时乱动同一块内存"——内存错误和一大类多线程数据竞争 bug 从根上不存在了。
注意
这也是 Rust 学习曲线陡峭的根源:编译器像个极其严格的审稿人,新手前两周会不停"跟借用检查器搏斗"(fighting the borrow checker)。社区共识是:熬过去之后,"编译通过 ≈ 基本能跑对"的体验会上瘾。
语法长什么样:五官速览
看懂下面这段,你对 Rust 的"长相"就有数了(很多东西会让你想起 TS):
// struct ≈ TS 的 interface + 数据本体 struct User { name: String, age: u32, // 无符号 32 位整数——类型精确到字节数 } // 函数:参数类型后置,和 TS 一样;最后一个表达式就是返回值 fn greeting(user: &User) -> String { // & 表示"借用":只是看看,不拿走所有权 format!("你好,{}({} 岁)", user.name, user.age) } fn main() { let user = User { name: String::from("站长"), age: 30, }; println!("{}", greeting(&user)); // Option:Rust 没有 null!可能不存在的值必须显式装进 Option let nickname: Option<String> = None; match nickname { Some(n) => println!("外号:{}", n), None => println!("没有外号"), // 不处理 None 分支?编译不过 } }
三个值得记住的点:
- 类型标注和 TS 神似(
name: String、-> String),毕竟 TS 的设计也借鉴了这一系语言 - 没有 null。"可能没有值"必须用
Option显式表达,且编译器强制你处理"没有"的分支——JS 的undefined is not a function、十亿美元的 null 错误,在 Rust 里是编译错误 - cargo 是 Rust 的 npm:
cargo add装依赖(包叫 crate,仓库是 crates.io)、cargo run运行、cargo test测试——体验被公认是所有语言里最好的包管理器之一
为什么"到处都是 Rust":你其实每天都在用
Rust 真正的爆发点,是大家发现开发者工具是它的完美主场——工具要处理海量文本/代码,性能就是体验,而工具崩溃或有漏洞影响的是所有开发者。盘点你雷达上出现过的:
- 你的 Next.js 项目:代码编译器 SWC、打包器 Turbopack 都是 Rust 写的——Vercel 用 Rust 重写了原本 JS 写的工具链,编译速度快了一个数量级
- ripgrep(rg):全世界最快的代码搜索工具,VS Code 的全局搜索底层就是它
- Tauri:用 Web 技术写桌面应用的框架,Electron 的轻量挑战者(第 3 单元细讲)
- uv / ruff:Python 圈最火的包管理器和 linter——注意,是用 Rust 写的 Python 工具,比原生 Python 工具快 10~100 倍
- Zed 编辑器、Deno 运行时的核心、Cloudflare / AWS / 微软的大量基础设施
看出模式了吗?"用 Rust 重写"的几乎全是工具和基础设施,而不是业务应用。原因很简单:
提示
分工格局:业务逻辑迭代快、性能瓶颈在数据库和网络,用 TS/Python 开发效率最高;工具和基础设施被百万人每天调用,慢 1 秒 = 百万人各浪费 1 秒,值得用开发更慢的 Rust 换极致性能。所以"Rust 火了"不意味着"你该用 Rust 写网站"——它在吃掉的是 C/C++ 和工具链的地盘,不是 TS 的地盘。
够用判断线
到这里,本课的目标已达成——下次看到 "written in Rust" 你应该能脑补出完整潜台词:"这工具直接编译成机器码、没有 GC 停顿、大概率比同类 JS/Python 工具快一个量级,代价是作者开发得比较辛苦。"
什么信号出现才值得系统学 Rust(那是几个月起步的投入):
- 你想写发给别人用的 CLI 工具(单文件、免安装、极快——Rust 是当前最优解之一)
- 你想用 Tauri 写桌面应用(前端仍是 Web 技术,但原生侧要碰 Rust)
- 你的某段 TS/Python 代码真实测出了性能瓶颈且优化到头了
在那之前,"看懂"就是最划算的深度。(本站有一个规划中的 Rust 完整 Track,等你哪天触发上面的信号再开。)
随堂测验
1. 「用 Rust 重写的工具通常快很多」,最主要的两个原因是?
2. Rust 的「所有权」机制解决的核心矛盾是什么?
3. let s2 = s1; 这行代码,在 JS 和 Rust 里的关键区别是?
4. 下列哪个判断最符合 Rust 目前的实际生态位?
划选正文任意文字可高亮、批注或加入复习卡
讨论
载入中…