Skip to content

Day 18: 模块系统

Rust的模块系统用于组织代码,提供了代码封装和作用域控制两种主要功能。通过模块可以:

  • 将相关代码组织在一起
  • 控制哪些内容对外可见(公有/私有)
  • 实现代码复用和命名空间管理

使用 mod 关键字定义模块:

// 定义模块
mod utils {
// 模块内可以定义函数、结构体、枚举等
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
// 私有函数,外部无法访问
fn helper() {
println!("helper 函数");
}
pub mod nested {
pub fn greet() {
println!("Hello!");
}
}
}
fn main() {
// 使用模块中的函数
println!("3 + 5 = {}", utils::add(3, 5));
println!("3 * 5 = {}", utils::multiply(3, 5));
// 访问嵌套模块
utils::nested::greet();
}

Rust默认所有内容是私有的。使用 pub 关键字使内容对外可见:

mod my_module {
// 私有项
fn private_function() {
println!("私有函数");
}
// 公有项
pub fn public_function() {
println!("公有函数");
}
// 仅对模块内可见(但对子模块可见)
pub(crate) fn crate_public_function() {
println!(" crate 内可见");
}
// 仅对父模块可见
pub(super) fn super_public_function() {
println!("父模块可见");
}
// 结构体字段的可见性
pub struct Config {
pub api_key: String, // 公开字段
internal: String, // 私有字段
}
impl Config {
pub fn new(api_key: &str) -> Self {
Config {
api_key: api_key.to_string(),
internal: String::new(),
}
}
}
}
fn main() {
my_module::public_function();
let config = my_module::Config::new("secret");
println!("API Key: {}", config.api_key);
// println!("{}", config.internal); // 编译错误!私有字段
}

使用 use 语句将模块引入当前作用域,避免重复写完整路径:

mod network {
pub mod http {
pub fn get(url: &str) {
println!("GET {}", url);
}
pub fn post(url: &str, body: &str) {
println!("POST {}: {}", url, body);
}
}
pub mod json {
pub fn parse(s: &str) {
println!("解析 JSON: {}", s);
}
pub fn stringify(obj: &str) {
println!("转 JSON: {}", obj);
}
}
}
// 完整路径
fn main() {
network::http::get("https://api.example.com");
network::json::parse("{}");
// 使用 use 简化
use network::http;
http::get("https://api.example.com");
http::post("https://api.example.com", "{}");
// 使用 as 起别名
use network::json::parse as parse_json;
use network::json::stringify as stringify_json;
parse_json("{\"name\": \"Rust\"}");
stringify_json("object");
}

使用 pub use 可以在当前位置导出子模块的项:

mod outer {
pub mod inner {
pub fn function() {
println!("inner::function");
}
}
// 将 inner::function 重导出到 outer 模块级别
pub use inner::function;
}
fn main() {
// 直接从 outer 访问
outer::function();
// 等价于 outer::inner::function()
}

Rust模块与文件系统一一对应。文件就是模块,目录通过 mod.rs 定义模块:

// src/main.rs 或 src/lib.rs
mod restaurant; // 引入 restaurant.rs 或 restaurant/mod.rs
src/restaurant.rs
pub mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {
println!("已添加到等待列表");
}
pub fn seat_at_table() {
println!("已安排座位");
}
}
pub mod menu {
pub struct MenuItem {
pub name: String,
pub price: f64,
}
impl MenuItem {
pub fn new(name: &str, price: f64) -> Self {
MenuItem {
name: name.to_string(),
price,
}
}
}
}
}
// 公开的 API
pub use front_of_house::hosting;
pub fn eat_at_restaurant() {
// 使用绝对路径
crate::front_of_house::hosting::add_to_waitlist();
// 使用相对路径
front_of_house::hosting::seat_at_table();
// 通过 pub use 重导出的路径
hosting::add_to_waitlist();
// 点餐
let menu_item = front_of_house::menu::MenuItem::new("汉堡", 25.0);
println!("点了 {},价格 {} 元", menu_item.name, menu_item.price);
}

使用 self 引用当前模块,super 引用父模块:

mod outer_module {
pub fn outer_function() {
println!("outer function");
}
mod inner_module {
pub fn inner_function() {
println!("inner function");
}
pub fn call_outer() {
// 调用父模块的函数
super::outer_function();
}
pub fn call_self() {
// 调用当前模块的其他函数
self::inner_function();
}
pub fn call_parent_method() {
super::outer_function();
}
}
pub fn public_entry() {
inner_module::call_outer();
inner_module::call_self();
}
}
fn main() {
outer_module::public_entry();
}

今天我们学习了Rust模块系统:

  • 模块定义:mod 关键字定义模块,模块内可包含函数、结构体、枚举等
  • 可见性控制:pub 关键字控制公有/私有,pub(crate)、pub(super) 限制可见范围
  • use语句:use 导入模块简化路径,as 起别名,pub use 重导出
  • 文件系统映射:文件对应模块,mod.rs 定义目录模块
  • self/super:self 引用当前模块,super 引用父模块

良好的模块化设计是构建大型Rust项目的基础。明天我们将学习包管理器 Cargo 的使用方法。