Rust 模块系统的清晰解释
本文为转载内容,由Google翻译生成,原文https://www.sheshbabu.com/posts/rust-module-system/
Rust 的模块系统令人惊讶地令人困惑并给初学者带来了很多挫败感。
在这篇文章中,我将使用实际示例解释模块系统,以便您清楚地了解其工作原理并可以立即开始在您的项目中应用它。
由于 Rust 的模块系统非常独特,我请求读者以开放的心态阅读这篇文章,不要将其与其他语言中模块的工作方式进行比较。
让我们使用这个文件结构来模拟一个真实世界的项目:
my_project
├── Cargo.toml
└─┬ src
├── main.rs
├── config.rs
├─┬ routes
│ ├── health_route.rs
│ └── user_route.rs
└─┬ models
└── user_model.rs
这些是我们使用模块的不同方式:
这 3 个例子足以解释 Rust 的模块系统如何工作。
示例1
让我们从第一个例子开始——在main.rs中导入config.rs。
// main.rs
fn main() {
println!("main");
}
// config.rs
fn print_config() {
println!("config");
}
每个人犯的第一个错误就是仅仅因为我们有诸如等文件config.rs,health_route.rs我们就认为这些文件是modules,并且可以从其他文件中导入它们。
以下是我们看到的内容(文件系统树)和编译器看到的内容(模块树):

令人惊讶的是,编译器只看到crate即我们的main.rs文件模块。这是因为我们需要在 Rust 中显式构建模块树 - 文件系统树到模块树之间没有隐式映射。
我们需要在 Rust 中明确构建模块树,没有隐式映射到文件系统
要将文件添加到模块树中,我们需要使用关键字将该文件声明为子模块mod。接下来让人感到困惑的是,你会认为我们在同一个文件中将文件声明为模块。但我们需要在另一个文件中声明它!因为我们只main.rs在模块树中,所以我们config.rs在中将其声明为子模块main.rs。
mod 关键字声明一个子模块 该mod关键字的语法如下:
mod my_module;
在这里,编译器在同一目录中寻找my_module.rs或my_module/mod.rs
my_project
├── Cargo.toml
└─┬ src
├── main.rs
└── my_module.rs
or
my_project
├── Cargo.toml
└─┬ src
├── main.rs
└─┬ my_module
└── mod.rs
由于main.rs和config.rs位于同一目录中,因此我们声明配置模块如下:
// main.rs
+ mod config;
fn main() {
+ config::print_config();
println!("main");
}
// config.rs
fn print_config() {
println!("config");
}
我们正在print_config使用::语法访问该函数。
模块树如下所示:

我们成功声明了config模块!但这还不足以调用print_config模块内部的函数config.rs。
Rust中的几乎所有内容默认都是私有的,我们需要使用pub关键字将函数公开:
pub 关键字使内容公开
// main.rs
mod config;
fn main() {
config::print_config();
println!("main");
}
// config.rs
- fn print_config() {
+ pub fn print_config() {
println!("config");
}
现在,一切正常。我们成功调用了在另一个文件中定义的函数!
示例 2
让我们尝试从main.rs中调用来自routes/health_route.rs中定义的函数print_health_route。
// main.rs
mod config;
fn main() {
config::print_config();
println!("main");
}
// routes/health_route.rs
fn print_health_route() {
println!("health_route");
}
正如我们前面讨论的,我们只能在同一个目录中使用mod关键字。my_module.rs my_module/mod.rs
因此,为了调用routes/health_route.rs来自内部的函数main.rs,我们需要做以下事情:
- 创建一个名为的文件
routes/mod.rs并routes在其中声明子模块main.rs - 声明
health_route子模块routes/mod.rs并将其公开 - 将内部函数
health_route.rs公开
my_project
├── Cargo.toml
└─┬ src
├── main.rs
├── config.rs
├─┬ routes
+ │ ├── mod.rs
│ ├── health_route.rs
│ └── user_route.rs
└─┬ models
└── user_model.rs
// main.rs
mod config;
+ mod routes;
fn main() {
+ routes::health_route::print_health_route();
config::print_config();
println!("main");
}
// routes/mod.rs
+ pub mod health_route;
// routes/health_route.rs
- fn print_health_route() {
+ pub fn print_health_route() {
println!("health_route");
}
模块树如下所示:

我们现在可以调用文件夹内的文件中定义的函数。