Rust 学习笔记 11:包与模块 (Packages & Modules)
“Organization is what you do before you do it, so that when you do it, it’s not all mixed up.” – A. A. Milne
欢迎来到 2025 年!
在完成了前 10 章的基础语法学习后,我们现在的 Rust 代码全都写在一个 main.rs 里。这对于写个猜数字游戏还行,但要写大项目,文件组织是必修课。
Rust 的模块系统 (Module System) 有点复杂,甚至被称为"新手劝退三大难"之一(另外俩是所有权和生命周期)。
1. 家族谱系:Package, Crate, Module
首先要分清三个概念:
- Package (包):Cargo 的功能单元。包含
Cargo.toml。一个 Package 可以包含多个 Binary Crate,但只能有一个 Library Crate。 - Crate (箱):编译单元。
main.rs是二进制 Crate 的根,lib.rs是库 Crate 的根。 - Module (模块):代码组织单元。用
mod关键字定义。
层级关系:Package -> (contains) -> Crates -> (contains) -> Modules。
2. 定义模块 (mod)
我们用一个经典的"餐馆"例子来理解。
在 lib.rs 中:
1pub mod front_of_house {
2 pub mod hosting {
3 pub fn add_to_waitlist() {}
4 }
5}
注意那个 pub。在 Rust 中,默认一切都是私有的 (private)。
- 父模块看不到子模块的内容,除非子模块加了
pub。 - 子模块可以看父模块的内容(子不嫌母丑?)。
3. 路径 (Paths)
要调用 add_to_waitlist,我们需要找到它的路径。
- 绝对路径:从 Crate 根开始,以
crate开头。crate::front_of_house::hosting::add_to_waitlist(); - 相对路径:从当前模块开始,以
self或super开头。front_of_house::hosting::add_to_waitlist();
4. use 关键字
每次都写全路径太累了,use 可以把路径引入当前作用域(建立软链接)。
1use crate::front_of_house::hosting;
2
3pub fn eat_at_restaurant() {
4 hosting::add_to_waitlist(); // 爽多了
5}
5. 文件分割
如果把所有代码都塞在 lib.rs 里,那跟塞在 main.rs 有什么区别?
Rust 允许我们将模块提取到独立文件中。
写法一(推荐):
src/lib.rs: mod front_of_house; (声明模块,内容去同名文件中找)
src/front_of_house.rs: (这里写模块内容)
写法二(子目录):
src/lib.rs: mod front_of_house;
src/front_of_house/mod.rs: (这里写模块内容,这是老写法,现在依然支持但不如写法一清爽)
6. 二进制 Crate 引用 库 Crate
如果你的 Package 同时包含 src/main.rs 和 src/lib.rs。
在 main.rs 中使用 lib.rs 的内容,必须把它当成外部库来用。
假设 Package 名字叫 my_project。
在 main.rs 中:
use my_project::front_of_house::hosting;
7. 小结
第十一篇笔记,也是 2025 年的第一篇。我们攻克了模块系统。
- Package 是 Cargo 管理的。
- Crate 是编译出的二进制或库。
- mod 是代码的文件夹。
- pub 是打开大门的钥匙(默认锁门)。
- use 是方便引用的快捷方式。
当你被 Module not found 搞疯的时候,记得回来看看这层级关系。
下一篇,我们将学习 常用集合 (String, Vector, HashMap)。这些是应用开发中最离不开的数据结构。
练习题:
- 尝试将
front_of_house模块提取到单独的文件src/front_of_house.rs中,并在lib.rs中重新导出它。 - 创建一个包含私有字段的结构体,并尝试在另一个模块中修改该私有字段,观察编译错误。
思考题:
Rust 的 mod 声明式系统(必须显式写 mod x; 才能加载文件)和 Go/Java/Python 的自动文件加载系统相比,有什么优缺点?
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
