模块系统
你会学到什么
- 用
mod声明模块,模块可以拆成独立文件。 - 默认私有,用
pub显式对外暴露。 - 用
use把路径引入当前作用域,少写前缀。
最小示例
mod geometry; // 对应 src/geometry.rs
use geometry::area; // 引入子模块
fn main() {
println!("{}", area::rectangle(2.0, 3.0));
}
运行代码
cd examples
cargo run -p rt_28_modules
cargo test -p rt_28_modules
代码讲解
模块树和文件系统对应:mod geometry; 会去找 src/geometry.rs,其中的 pub mod area; 又对应 src/geometry/area.rs。
// src/geometry.rs
pub mod area;
pub fn describe() -> &'static str { "geometry module" }
可见性是分层的:只有标了 pub 的项才能被父模块访问。use 只是创建一个简写别名,不改变可见性。路径以 crate:: 开头表示从 crate 根算起,super:: 表示上一层。
常见错误
忘记把要对外使用的项标成 pub:
mod geometry {
fn area() -> f64 { 1.0 } // 私有
}
geometry::area(); // ❌ function `area` is private
加上 pub fn area。
练习
- 给
geometry加一个perimeter子模块。 - 用
pub use把深层函数“重导出”到模块顶层,简化调用路径。
小结
模块系统用 mod/pub/use 把代码分层组织,默认私有的设计让你显式地决定 API 边界。
下一步
把可复用逻辑抽成库 crate,再用 workspace 管理多个 crate。下一章学习库 crate 与 workspace。
完整示例代码
下面是 examples/28_modules/ 的完整源码。无需 clone 仓库,直接在页面上阅读、复制、对照运行。
examples/28_modules/src/main.rs
//! 演示模块系统:mod 声明、pub 可见性、use 引入。
mod geometry;
use geometry::area;
fn main() {
println!("{}", geometry::describe());
println!("rectangle = {}", area::rectangle(2.0, 3.0));
println!("circle = {:.2}", area::circle(1.0));
}
#[cfg(test)]
mod tests {
use crate::geometry::area;
#[test]
fn rectangle_area() {
assert_eq!(area::rectangle(2.0, 3.0), 6.0);
}
#[test]
fn circle_area() {
assert!((area::circle(1.0) - std::f64::consts::PI).abs() < 1e-9);
}
} examples/28_modules/src/geometry.rs
//! geometry 模块:聚合子模块并暴露公共接口。
pub mod area;
/// 公开函数,可被父模块通过 `geometry::describe()` 调用。
pub fn describe() -> &'static str {
"geometry module"
} examples/28_modules/src/geometry/area.rs
//! area 子模块:面积计算。
/// 矩形面积。
pub fn rectangle(width: f64, height: f64) -> f64 {
width * height
}
/// 圆面积。
pub fn circle(radius: f64) -> f64 {
std::f64::consts::PI * radius * radius
} examples/28_modules/Cargo.toml
[package]
name = "rt_28_modules"
version.workspace = true
edition.workspace = true
publish.workspace = true