
随着程序变得越来越复杂,我们需要将代码组织成清晰、可维护的结构。Rust的模块系统(Module System)正是为此而设计的,它提供了强大的代码组织能力,包括模块定义、可见性控制、路径解析等。
Rust的模块系统是构建大型项目的基石,它帮助你:
本文将全面介绍Rust的模块系统,包括:
通过本文的学习,你将能够:
模块是代码的组织单元,用于将相关功能分组在一起。模块可以包含:
模块的好处:
使用 mod 关键字定义模块:
// 定义一个模块
mod math {
fn add(x: i32, y: i32) -> i32 {
x + y
}
fn subtract(x: i32, y: i32) -> i32 {
x - y
}
}
fn main() {
// 调用模块中的函数需要使用路径
// math::add(10, 20); // 默认私有,无法访问
}默认情况下,模块内的所有项都是私有的,只能在同一模块内访问:
mod math {
// 私有函数(默认)
fn add_private(x: i32, y: i32) -> i32 {
x + y
}
// 公开函数
pub fn add_public(x: i32, y: i32) -> i32 {
x + y
}
// 私有函数可以调用私有函数
fn multiply(x: i32, y: i32) -> i32 {
x * y
}
pub fn square(x: i32) -> i32 {
multiply(x, x) // 可以调用同模块的私有函数
}
}
fn main() {
// math::add_private(10, 20); // 错误!私有函数无法访问
println!("{}", math::add_public(10, 20)); // ✅ 可以访问
println!("{}", math::square(5)); // ✅ 可以访问
}
pub 关键字使模块项对外可见:
mod calculator {
// 私有函数
fn internal_add(x: i32, y: i32) -> i32 {
x + y
}
// 公开函数
pub fn add(x: i32, y: i32) -> i32 {
internal_add(x, y) // 可以调用私有函数
}
pub fn multiply(x: i32, y: i32) -> i32 {
x * y
}
}
fn main() {
println!("{}", calculator::add(10, 20));
println!("{}", calculator::multiply(5, 6));
// calculator::internal_add(10, 20); // 错误!私有函数
}
Rust提供了不同级别的可见性:
// 私有(默认)
fn private_function() {}
// 公开到当前模块的父级
pub fn public_function() {}
// 公开到当前crate
pub(crate) fn crate_public_function() {}
// 公开到指定路径
pub(super) fn super_public_function() {} // 父模块可见
pub(in crate::path) fn path_public_function() {} // 指定路径可见示例:
mod outer {
pub mod inner {
// 只在inner模块和其父模块可见
pub(super) fn super_function() {
println!("super可见");
}
// 在当前crate可见
pub(crate) fn crate_function() {
println!("crate可见");
}
// 完全公开
pub fn public_function() {
println!("完全公开");
}
}
pub fn test() {
// 可以访问super_function(父模块)
inner::super_function();
inner::crate_function();
inner::public_function();
}
}
fn main() {
// outer::inner::super_function(); // 错误!不能从main访问
outer::inner::crate_function(); // ✅ 可以
outer::inner::public_function(); // ✅ 可以
outer::test(); // ✅ 可以
}
use 关键字用于导入模块,简化路径:
mod math {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn multiply(x: i32, y: i32) -> i32 {
x * y
}
}
// 方式1:使用完整路径
fn main() {
println!("{}", math::add(10, 20));
}
// 方式2:使用use导入
use math::add;
fn main() {
println!("{}", add(10, 20)); // 不需要math::前缀
}mod math {
pub fn add(x: i32, y: i32) -> i32 { x + y }
pub fn subtract(x: i32, y: i32) -> i32 { x - y }
pub fn multiply(x: i32, y: i32) -> i32 { x * y }
// 返回 Result 处理除零错误
pub fn divide(x: i32, y: i32) -> Result<i32, &'static str> {
if y == 0 {
Err("除数不能为 0")
} else {
Ok(x / y)
}
}
}
use math::{add, subtract, multiply, divide};
fn main() {
println!("{}", add(10, 5));
println!("{}", subtract(10, 5));
println!("{}", multiply(10, 5));
// 调用 divide 时处理可能的错误
match divide(10, 0) {
Ok(result) => println!("{}", result),
Err(err) => println!("{}", err),
}
}
mod math {
pub fn calculate(x: i32, y: i32) -> i32 {
x + y
}
}
// 重命名避免冲突
use math::calculate as math_calc;
fn calculate(x: f64, y: f64) -> f64 {
x * y
}
fn main() {
println!("{}", math_calc(10, 20)); // 整数计算
println!("{}", calculate(3.0, 4.0)); // 浮点数计算
}fn function() {
println!("顶层函数");
}
mod outer {
fn function() {
println!("outer模块的函数");
}
mod inner {
use super::function; // 导入父模块的函数
pub fn test() {
function(); // 调用父模块的函数
}
}
pub fn test() {
inner::test();
}
}
fn main() {
outer::test(); // 输出: "outer模块的函数"
}mod level1 {
pub mod level2 {
pub mod level3 {
pub fn function() {
println!("level3的函数");
}
}
}
}
fn main() {
// 绝对路径:从crate根开始
crate::level1::level2::level3::function();
// 相对路径:从当前模块开始
level1::level2::level3::function();
// 使用use简化
use level1::level2::level3::function;
function();
}mod a {
pub fn function_a() {
println!("A");
}
pub mod b {
pub fn function_b() {
println!("B");
}
pub mod c {
pub fn function_c() {
// 调用父模块的函数
super::function_b();
// 调用顶层模块的函数
crate::a::function_a();
}
}
}
}
fn main() {
a::b::c::function_c(); // 输出: B, A
}模块定义在文件中:
// main.rs
mod math {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
}
fn main() {
println!("{}", math::add(10, 20));
}使用独立的文件:
// math.rs
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn subtract(x: i32, y: i32) -> i32 {
x - y
}// main.rs
mod math; // 声明模块,从math.rs加载
fn main() {
println!("{}", math::add(10, 20));
}使用目录组织模块:
project/
├── Cargo.toml
└── src/
├── main.rs
├── math.rs
└── utils/
├── mod.rs # utils模块的入口
├── string.rs
└── validation.rs// src/main.rs
mod math;
mod utils;
fn main() {
math::add(10, 20);
utils::string::reverse("hello");
}// src/utils/mod.rs
pub mod string;
pub mod validation;// src/utils/string.rs
pub fn reverse(s: &str) -> String {
s.chars().rev().collect()
}// src/utils/validation.rs
pub fn is_email(email: &str) -> bool {
email.contains('@')
}calculator/
├── Cargo.toml
└── src/
├── main.rs
├── math/
│ ├── mod.rs
│ ├── basic.rs # 基础运算
│ └── advanced.rs # 高级运算
└── utils/
├── mod.rs
└── helper.rs// src/main.rs
mod math;
mod utils;
use math::{basic, advanced};
use utils::helper;
fn main() {
println!("10 + 5 = {}", basic::add(10, 5));
println!("10 * 5 = {}", basic::multiply(10, 5));
println!("2^3 = {}", advanced::power(2, 3));
let result = helper::format_result(42);
println!("{}", result);
}// src/math/mod.rs
pub mod basic;
pub mod advanced;// src/math/basic.rs
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn subtract(x: i32, y: i32) -> i32 {
x - y
}
pub fn multiply(x: i32, y: i32) -> i32 {
x * y
}
pub fn divide(x: i32, y: i32) -> Option<i32> {
if y != 0 {
Some(x / y)
} else {
None
}
}// src/math/advanced.rs
pub fn power(base: i32, exp: u32) -> i64 {
let mut result = 1i64;
for _ in 0..exp {
result *= base as i64;
}
result
}
pub fn sqrt(x: f64) -> f64 {
x.sqrt()
}// src/utils/mod.rs
pub mod helper;// src/utils/helper.rs
pub fn format_result(value: i32) -> String {
format!("结果: {}", value)
}使用 pub use 重新导出,创建更友好的API:
// src/math/mod.rs
mod basic;
mod advanced;
// 重新导出,用户可以直接使用 math::add 而不需要 math::basic::add
pub use basic::{add, subtract, multiply, divide};
pub use advanced::{power, sqrt};// src/main.rs
mod math;
use math::{add, multiply, power}; // 简洁的导入
fn main() {
println!("{}", add(10, 5));
println!("{}", multiply(10, 5));
println!("{}", power(2, 8));
}// 为不同用户提供不同级别的API
mod math {
pub mod internal {
pub fn complex_calculation() {}
}
pub mod public {
// 公开API
pub fn simple_calculation() {
internal::complex_calculation(); // 可以使用内部实现
}
}
// 重新导出公开API到顶层
pub use public::simple_calculation;
}
fn main() {
math::simple_calculation(); // 用户只需使用简单API
// math::internal::complex_calculation(); // 错误!内部实现
}// ✅ 好的命名
mod math_utils;
mod string_processing;
mod data_validation;
// ❌ 不好的命名
mod utils; // 太泛泛
mod helper; // 不够具体
mod m1; // 不描述性单一职责原则:
// ✅ 好的组织:每个模块有明确的职责
mod math {
pub mod basic;
pub mod advanced;
}
mod io {
pub mod file;
pub mod network;
}
// ❌ 不好的组织:混合职责
mod utils {
pub fn add() {}
pub fn read_file() {} // 不同职责混在一起
pub fn validate() {}
}最小公开原则:
mod api {
// 公开接口
pub fn public_function() {
// 使用私有实现
private_helper();
}
// 私有实现细节
fn private_helper() {
// 实现细节
}
}tools_lib/
├── Cargo.toml
└── src/
├── lib.rs # 库的入口(如果作为库)
├── main.rs # 可执行程序的入口
├── string_tools/
│ ├── mod.rs
│ ├── formatting.rs
│ └── validation.rs
├── math_tools/
│ ├── mod.rs
│ ├── arithmetic.rs
│ └── statistics.rs
└── io_tools/
├── mod.rs
└── file_ops.rs// src/lib.rs(如果作为库)
pub mod string_tools;
pub mod math_tools;
pub mod io_tools;
// 重新导出常用函数
pub use string_tools::{reverse, capitalize, is_email};
pub use math_tools::{mean, std_dev, factorial};// src/string_tools/mod.rs
pub mod formatting;
pub mod validation;
pub use formatting::{reverse, capitalize, to_uppercase};
pub use validation::{is_email, is_phone, is_url};// src/string_tools/formatting.rs
pub fn reverse(s: &str) -> String {
s.chars().rev().collect()
}
pub fn capitalize(s: &str) -> String {
let mut chars: Vec<char> = s.chars().collect();
if !chars.is_empty() {
chars[0] = chars[0].to_uppercase().next().unwrap();
}
chars.into_iter().collect()
}
pub fn to_uppercase(s: &str) -> String {
s.to_uppercase()
}// src/string_tools/validation.rs
pub fn is_email(email: &str) -> bool {
email.contains('@') && email.contains('.')
}
pub fn is_phone(phone: &str) -> bool {
phone.chars().all(|c| c.is_numeric()) && phone.len() >= 10
}
pub fn is_url(url: &str) -> bool {
url.starts_with("http://") || url.starts_with("https://")
}// src/math_tools/mod.rs
pub mod arithmetic;
pub mod statistics;
pub use arithmetic::{add, multiply, factorial};
pub use statistics::{mean, std_dev};// src/main.rs
use tools_lib::{reverse, is_email, mean, factorial};
fn main() {
println!("{}", reverse("Hello"));
println!("{}", is_email("test@example.com"));
let numbers = vec![1.0, 2.0, 3.0, 4.0, 5.0];
println!("平均值: {}", mean(&numbers));
println!("5! = {}", factorial(5));
}// 错误:使用未声明的模块
fn main() {
math::add(10, 20); // 编译错误!
}
// 解决:先声明模块
mod math {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
}
fn main() {
math::add(10, 20); // ✅ 正确
}mod math {
fn internal_add(x: i32, y: i32) -> i32 {
x + y
}
}
fn main() {
// math::internal_add(10, 20); // 错误!私有函数
// 解决:使用pub关键字
// mod math {
// pub fn internal_add(x: i32, y: i32) -> i32 {
// x + y
// }
// }
}// 错误:文件结构不对
// src/
// ├── main.rs
// └── utils.rs
// main.rs中:mod utils; // 正确
// 错误:缺少mod.rs
// src/
// ├── main.rs
// └── utils/
// └── helper.rs
// 需要:src/utils/mod.rs 文件创建一个模块化的数学库,包含基础运算、三角函数、统计函数等模块。
创建一个工具函数库,包含字符串处理、日期时间、文件操作等模块。
设计一个简单的游戏项目,将游戏逻辑、渲染、输入处理等分别组织成模块。
将一个单一文件的程序重构为模块化的结构。
mod 关键字定义模块pub 关键字控制访问权限use 关键字简化路径pub use 创建友好API