Rust 模块与包管理详解
概述
Rust 的模块系统提供了组织代码的强大工具。通过模块、包和 crate,你可以将代码组织成可重用、可维护的结构。
包(Package)和 Crate
包和 Crate 的关系
-
包(Package):用于构建、测试和共享 crate 的 Cargo 功能
-
Crate:一个模块树,它产生一个库或可执行文件
-
模块(Module):使用
mod关键字定义的代码组织单元
创建包
cargo new my_project
这会创建以下结构:
my_project/
├── Cargo.toml
└── src/
└── main.rs
包的规则
-
一个包必须包含 0 个或 1 个库 crate
-
可以包含任意数量的二进制 crate
-
至少包含一个 crate(库或二进制)
定义模块
基本 mod 关键字
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}
模块树
crate
└── front_of_house
├── hosting
│ ├── add_to_waitlist
│ └── seat_at_table
└── serving
├── take_order
├── serve_order
└── take_payment
路径
绝对路径
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
}
相对路径
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// 相对路径
front_of_house::hosting::add_to_waitlist();
}
使用 super 访问父模块
fn serve_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}
fn cook_order() {}
}
公开模块
pub 关键字
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// 现在可以访问了
front_of_house::hosting::add_to_waitlist();
}
结构体的可见性
mod back_of_house {
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String, // 私有字段
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("桃子"),
}
}
}
}
pub fn eat_at_restaurant() {
// 可以创建实例
let mut meal = back_of_house::Breakfast::summer("黑麦");
// 可以访问公共字段
meal.toast = String::from("小麦");
// 不能访问私有字段
// meal.seasonal_fruit = String::from("蓝莓");
}
枚举的可见性
mod back_of_house {
pub enum Appetizer {
Soup,
Salad,
}
}
pub fn eat_at_restaurant() {
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
}
使用 use 关键字
导入路径
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
导入函数与结构体
// 导入函数(习惯上使用父模块)
use std::collections::HashMap;
// 导入结构体(习惯上直接导入)
use std::collections::HashMap;
// 导入枚举(习惯上直接导入)
use std::collections::HashMap;
使用 as 提供别名
use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
Ok(())
}
fn function2() -> IoResult<()> {
Ok(())
}
重新导出
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
使用嵌套路径
use std::cmp::Ordering;
use std::io;
// 等价于:
use std::{cmp::Ordering, io};
使用 glob 运算符
use std::collections::*;
将模块拆分到不同文件
基本文件结构
src/
├── main.rs
└── front_of_house/
├── mod.rs
├── hosting.rs
└── serving.rs
front_of_house/mod.rs
pub mod hosting;
pub mod serving;
front_of_house/hosting.rs
pub fn add_to_waitlist() {}
front_of_house/serving.rs
pub fn take_order() {}
main.rs
mod front_of_house;
use front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
使用外部包
添加依赖
在 Cargo.toml 中添加:
[dependencies]
rand = "0.8.5"
使用外部包
use rand::Rng;
fn main() {
let secret_number = rand::thread_rng().gen_range(1..=100);
println!("随机数: {}", secret_number);
}
常用外部包
[dependencies]
serde = "1.0" # 序列化/反序列化
serde_json = "1.0" # JSON 支持
tokio = { version = "1.0", features = ["full"] } # 异步运行时
reqwest = { version = "0.11", features = ["json"] } # HTTP 客户端
clap = "3.0" # 命令行参数解析
log = "0.4" # 日志门面
env_logger = "0.9" # 日志实现
二进制和库 Crate
项目结构
my_project/
├── Cargo.toml
└── src/
├── main.rs # 二进制 crate
└── lib.rs # 库 crate
lib.rs
pub mod front_of_house;
pub use front_of_house::hosting;
main.rs
use my_project::hosting;
fn main() {
hosting::add_to_waitlist();
}
多个二进制文件
my_project/
├── Cargo.toml
└── src/
├── main.rs
├── lib.rs
└── bin/
├── extra1.rs
└── extra2.rs
工作空间(Workspace)
创建工作空间
my_workspace/
├── Cargo.toml
├── src/
│ └── main.rs
├── adder/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs
└── add-one/
├── Cargo.toml
└── src/
└── lib.rs
Cargo.toml(工作空间)
[workspace]
members = [
"adder",
"add-one",
]
adder/Cargo.toml
[package]
name = "adder"
version = "0.1.0"
edition = "2021"
[dependencies]
add-one = { path = "../add-one" }
adder/src/lib.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn add_two(a: i32) -> i32 {
add_one::add_one(a) + 1
}
add-one/Cargo.toml
[package]
name = "add-one"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8.5"
add-one/src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
实际应用示例
创建一个简单的库
my_lib/
├── Cargo.toml
└── src/
├── lib.rs
├── math.rs
└── string.rs
Cargo.toml
[package]
name = "my_lib"
version = "0.1.0"
edition = "2021"
[dependencies]
src/lib.rs
pub mod math;
pub mod string;
pub use math::add;
pub use string::reverse;
src/math.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
src/string.rs
pub fn reverse(s: &str) -> String {
s.chars().rev().collect()
}
pub fn to_uppercase(s: &str) -> String {
s.to_uppercase()
}
使用库
[dependencies]
my_lib = { path = "../my_lib" }
use my_lib::{add, reverse};
fn main() {
let sum = add(5, 3);
println!("5 + 3 = {}", sum);
let reversed = reverse("hello");
println!("反转后的字符串: {}", reversed);
}
总结
本教程详细介绍了 Rust 的模块与包管理:
-
包和 Crate:
- 包是 Cargo 的功能
- Crate 是模块树
- 一个包可以包含多个 crate
-
模块系统:
- 使用
mod关键字定义模块 - 模块树结构
- 绝对路径和相对路径
- 使用
-
可见性:
- 使用
pub关键字公开模块 - 结构体和枚举的可见性规则
- 使用
super访问父模块
- 使用
-
use 关键字:
- 导入路径
- 提供别名
- 重新导出
- 嵌套路径和 glob 运算符
-
文件组织:
- 将模块拆分到不同文件
- 模块文件命名约定
-
外部包:
- 添加依赖
- 使用外部包
- 常用外部包介绍
-
工作空间:
- 创建工作空间
- 管理多个相关包
Rust 的模块系统提供了强大的代码组织能力,合理使用模块和包可以让代码更加清晰、可维护和可重用。
下一步
在下一教程中,我们将学习 Rust 的特质(Trait),这是 Rust 中定义共享行为的重要方式。我们将了解:
-
定义和使用特质
-
特质边界
-
默认实现
-
特质对象
-
关联类型
继续学习 Rust,掌握这门强大语言的更多特性!

