本章概述
模块系统是Rust中组织代码的核心机制。通过模块,我们可以将相关的功能组织在一起,控制代码的可见性,并创建清晰的代码结构。本章将深入探讨Rust的模块系统,包括模块定义、可见性控制、包管理和项目组织。
学习目标
- 🎯 理解模块的概念和作用
- 🎯 掌握模块的定义和使用
- 🎯 学会控制代码的可见性
- 🎯 了解包和Crate的概念
- 🎯 掌握外部依赖的使用
- 🎯 学会组织大型项目结构
7.1 模块基础
7.1.1 什么是模块
fn main() {
println!("📦 模块系统基础");
println!("===============");
demonstrate_basic_modules();
demonstrate_nested_modules();
demonstrate_module_paths();
}
// 基本模块定义
mod math {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
// 私有函数,模块外无法访问
fn internal_calculation() -> i32 {
42
}
pub fn get_magic_number() -> i32 {
internal_calculation() // 模块内可以访问私有函数
}
}
// 嵌套模块
mod geometry {
pub mod shapes {
pub struct Rectangle {
pub width: f64,
pub height: f64,
}
impl Rectangle {
pub fn new(width: f64, height: f64) -> Self {
Rectangle { width, height }
}
pub fn area(&self) -> f64 {
self.width * self.height
}
pub fn perimeter(&self) -> f64 {
2.0 * (self.width + self.height)
}
}
pub struct Circle {
pub radius: f64,
}
impl Circle {
pub fn new(radius: f64) -> Self {
Circle { radius }
}
pub fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
pub fn circumference(&self) -> f64 {
2.0 * std::f64::consts::PI * self.radius
}
}
}
pub mod calculations {
use super::shapes::{Rectangle, Circle};
pub fn compare_areas(rect: &Rectangle, circle: &Circle) -> String {
let rect_area = rect.area();
let circle_area = circle.area();
if rect_area > circle_area {
format!("矩形面积 ({:.2}) 大于圆形面积 ({:.2})", rect_area, circle_area)
} else if circle_area > rect_area {
format!("圆形面积 ({:.2}) 大于矩形面积 ({:.2})", circle_area, rect_area)
} else {
format!("矩形和圆形面积相等 ({:.2})", rect_area)
}
}
}
}
// 使用use语句简化路径
use geometry::shapes::{Rectangle, Circle};
use geometry::calculations::compare_areas;
fn demonstrate_basic_modules() {
println!("\n基本模块使用:");
// 使用模块中的函数
let sum = math::add(10, 5);
let diff = math::subtract(10, 5);
let magic = math::get_magic_number();
println!("10 + 5 = {}", sum);
println!("10 - 5 = {}", diff);
println!("魔法数字: {}", magic);
// 尝试访问私有函数会编译错误
// let internal = math::internal_calculation(); // 编译错误
}
fn demonstrate_nested_modules() {
println!("\n嵌套模块使用:");
// 创建几何图形
let rect = Rectangle::new(5.0, 3.0);
let circle = Circle::new(2.0);
println!("矩形 ({}x{}): 面积 = {:.2}, 周长 = {:.2}",
rect.width, rect.height, rect.area(), rect.perimeter());
println!("圆形 (半径 {}): 面积 = {:.2}, 周长 = {:.2}",
circle.radius, circle.area(), circle.circumference());
// 比较面积
let comparison = compare_areas(&rect, &circle);
println!("比较结果: {}", comparison);
}
fn demonstrate_module_paths() {
println!("\n模块路径演示:");
// 绝对路径
let rect1 = crate::geometry::shapes::Rectangle::new(4.0, 6.0);
// 相对路径(通过use语句)
let rect2 = Rectangle::new(3.0, 8.0);
println!("矩形1面积: {:.2}", rect1.area());
println!("矩形2面积: {:.2}", rect2.area());
// 使用self和super
demonstrate_self_super();
}
mod parent {
pub fn parent_function() {
println!("父模块函数");
}
pub mod child {
pub fn child_function() {
println!("子模块函数");
// 使用super访问父模块
super::parent_function();
// 使用self访问当前模块
self::another_child_function();
}
pub fn another_child_function() {
println!("另一个子模块函数");
}
}
}
fn demonstrate_self_super() {
println!("\nself和super演示:");
parent::child::child_function();
}
rustc module_basics.rs && ./module_basics
7.1.2 模块的可见性
fn main() {
println!("🔒 可见性控制");
println!("============");
demonstrate_pub_visibility();
demonstrate_pub_crate();
demonstrate_pub_super();
demonstrate_pub_in();
}
// 公共模块
pub mod public_module {
pub fn public_function() {
println!("这是一个公共函数");
}
fn private_function() {
println!("这是一个私有函数");
}
pub fn call_private() {
private_function(); // 模块内可以调用私有函数
}
pub struct PublicStruct {
pub public_field: i32,
private_field: i32,
}
impl PublicStruct {
pub fn new(public_value: i32, private_value: i32) -> Self {
PublicStruct {
public_field: public_value,
private_field: private_value,
}
}
pub fn get_private_field(&self) -> i32 {
self.private_field
}
pub fn set_private_field(&mut self, value: i32) {
self.private_field = value;
}
}
// 公共枚举
pub enum PublicEnum {
Variant1,
Variant2(i32),
Variant3 { field: String },
}
}
// 私有模块
mod private_module {
pub fn function_in_private_module() {
println!("私有模块中的公共函数");
}
}
// pub(crate) 示例
pub(crate) mod crate_visible {
pub(crate) fn crate_function() {
println!("整个crate可见的函数");
}
pub(crate) struct CrateStruct {
pub(crate) field: i32,
}
}
// pub(super) 示例
mod parent_module {
pub(super) fn parent_visible_function() {
println!("父模块可见的函数");
}
pub mod child_module {
pub fn child_function() {
// 可以访问父模块的pub(super)函数
super::parent_visible_function();
}
pub(super) fn super_visible_function() {
println!("对父模块可见的函数");
}
}
pub fn test_super_visibility() {
child_module::super_visible_function(); // 可以访问
}
}
// pub(in path) 示例
mod outer {
pub mod inner {
pub(in crate::outer) fn restricted_function() {
println!("只在outer模块内可见的函数");
}
pub mod deep {
pub fn deep_function() {
// 可以访问,因为在outer模块内
super::restricted_function();
}
}
}
pub fn outer_function() {
inner::restricted_function(); // 可以访问
inner::deep::deep_function();
}
}
fn demonstrate_pub_visibility() {
println!("\n基本可见性:");
// 访问公共模块的公共函数
public_module::public_function();
public_module::call_private();
// 创建公共结构体
let mut s = public_module::PublicStruct::new(10, 20);
println!("公共字段: {}", s.public_field);
println!("私有字段: {}", s.get_private_field());
s.public_field = 15; // 可以直接修改公共字段
s.set_private_field(25); // 通过方法修改私有字段
println!("修改后 - 公共字段: {}, 私有字段: {}",
s.public_field, s.get_private_field());
// 使用公共枚举
let enum_variants = vec![
public_module::PublicEnum::Variant1,
public_module::PublicEnum::Variant2(42),
public_module::PublicEnum::Variant3 {
field: "Hello".to_string()
},
];
for (i, variant) in enum_variants.iter().enumerate() {
match variant {
public_module::PublicEnum::Variant1 =>
println!("枚举 {}: Variant1", i),
public_module::PublicEnum::Variant2(value) =>
println!("枚举 {}: Variant2({})", i, value),
public_module::PublicEnum::Variant3 { field } =>
println!("枚举 {}: Variant3 {{ field: {} }}", i, field),
}
}
// 无法访问私有模块
// private_module::function_in_private_module(); // 编译错误
}
fn demonstrate_pub_crate() {
println!("\npub(crate) 可见性:");
// 可以访问crate级别可见的函数和结构体
crate_visible::crate_function();
let crate_struct = crate_visible::CrateStruct { field: 100 };
println!("Crate结构体字段: {}", crate_struct.field);
}
fn demonstrate_pub_super() {
println!("\npub(super) 可见性:");
parent_module::child_module::child_function();
parent_module::test_super_visibility();
// 无法直接访问pub(super)函数
// parent_module::parent_visible_function(); // 编译错误
}
fn demonstrate_pub_in() {
println!("\npub(in path) 可见性:");
outer::outer_function();
// 无法直接访问受限函数
// outer::inner::restricted_function(); // 编译错误
}
rustc visibility_demo.rs && ./visibility_demo
7.2 文件模块系统
7.2.1 将模块分离到文件
// 声明模块(对应文件)
mod math_operations;
mod geometry;
mod utils;
// 使用模块
use math_operations::{basic, advanced};
use geometry::shapes::Rectangle;
use utils::formatter;
fn main() {
println!("📁 文件模块系统");
println!("===============");
demonstrate_file_modules();
demonstrate_module_hierarchy();
}
fn demonstrate_file_modules() {
println!("\n文件模块演示:");
// 使用基本数学运算
let sum = basic::add(10, 5);
let product = basic::multiply(4, 7);
println!("基本运算: 10 + 5 = {}, 4 × 7 = {}", sum, product);
// 使用高级数学运算
let power = advanced::power(2, 8);
let factorial = advanced::factorial(5);
println!("高级运算: 2^8 = {}, 5! = {}", power, factorial);
// 使用几何模块
let rect = Rectangle::new(5.0, 3.0);
println!("矩形面积: {:.2}", rect.area());
// 使用工具模块
let formatted = formatter::format_number(1234567.89);
println!("格式化数字: {}", formatted);
}
fn demonstrate_module_hierarchy() {
println!("\n模块层次结构:");
// 展示模块的层次结构
println!("math_operations::");
println!(" ├── basic::");
println!(" │ ├── add()");
println!(" │ ├── subtract()");
println!(" │ ├── multiply()");
println!(" │ └── divide()");
println!(" └── advanced::");
println!(" ├── power()");
println!(" ├── factorial()");
println!(" └── fibonacci()");
println!("");
println!("geometry::");
println!(" └── shapes::");
println!(" ├── Rectangle");
println!(" ├── Circle");
println!(" └── Triangle");
println!("");
println!("utils::");
println!(" ├── formatter::");
println!(" └── validator::");
}
// math_operations.rs - 数学运算模块
pub mod basic {
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
pub fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("除零错误".to_string())
} else {
Ok(a / b)
}
}
}
pub mod advanced {
pub fn power(base: i32, exp: u32) -> i64 {
(base as i64).pow(exp)
}
pub fn factorial(n: u32) -> u64 {
if n <= 1 {
1
} else {
(1..=n as u64).product()
}
}
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
}
}
pub fn gcd(mut a: u32, mut b: u32) -> u32 {
while b != 0 {
let temp = b;
b = a % b;
a = temp;
}
a
}
pub fn lcm(a: u32, b: u32) -> u32 {
a * b / gcd(a, b)
}
}
// 私有辅助函数
fn _helper_function() {
// 这个函数只在当前模块内可见
}
// geometry/mod.rs - 几何模块的入口文件
pub mod shapes;
pub mod calculations;
// 重新导出常用类型
pub use shapes::{Rectangle, Circle, Triangle};
pub use calculations::*;
// geometry/shapes.rs - 几何图形定义
use std::f64::consts::PI;
#[derive(Debug, Clone)]
pub struct Rectangle {
pub width: f64,
pub height: f64,
}
impl Rectangle {
pub fn new(width: f64, height: f64) -> Self {
Rectangle { width, height }
}
pub fn area(&self) -> f64 {
self.width * self.height
}
pub fn perimeter(&self) -> f64 {
2.0 * (self.width + self.height)
}
pub fn is_square(&self) -> bool {
(self.width - self.height).abs() < f64::EPSILON
}
}
#[derive(Debug, Clone)]
pub struct Circle {
pub radius: f64,
}
impl Circle {
pub fn new(radius: f64) -> Self {
Circle { radius }
}
pub fn area(&self) -> f64 {
PI * self.radius * self.radius
}
pub fn circumference(&self) -> f64 {
2.0 * PI * self.radius
}
pub fn diameter(&self) -> f64 {
2.0 * self.radius
}
}
#[derive(Debug, Clone)]
pub struct Triangle {
pub a: f64,
pub b: f64,
pub c: f64,
}
impl Triangle {
pub fn new(a: f64, b: f64, c: f64) -> Result<Self, String> {
if a + b > c && b + c > a && a + c > b {
Ok(Triangle { a, b, c })
} else {
Err("无效的三角形边长".to_string())
}
}
pub fn area(&self) -> f64 {
// 使用海伦公式
let s = (self.a + self.b + self.c) / 2.0;
(s * (s - self.a) * (s - self.b) * (s - self.c)).sqrt()
}
pub fn perimeter(&self) -> f64 {
self.a + self.b + self.c
}
pub fn is_right_triangle(&self) -> bool {
let mut sides = [self.a, self.b, self.c];
sides.sort_by(|a, b| a.partial_cmp(b).unwrap());
let [a, b, c] = sides;
(a * a + b * b - c * c).abs() < f64::EPSILON
}
}
// geometry/calculations.rs - 几何计算函数
use super::shapes::{Rectangle, Circle, Triangle};
pub fn total_area_rectangles(rectangles: &[Rectangle]) -> f64 {
rectangles.iter().map(|r| r.area()).sum()
}
pub fn total_area_circles(circles: &[Circle]) -> f64 {
circles.iter().map(|c| c.area()).sum()
}
pub fn compare_rectangle_areas(r1: &Rectangle, r2: &Rectangle) -> std::cmp::Ordering {
r1.area().partial_cmp(&r2.area()).unwrap()
}
pub fn find_largest_rectangle(rectangles: &[Rectangle]) -> Option<&Rectangle> {
rectangles.iter().max_by(|a, b| a.area().partial_cmp(&b.area()).unwrap())
}
pub fn rectangles_with_area_greater_than(rectangles: &[Rectangle], min_area: f64) -> Vec<&Rectangle> {
rectangles.iter().filter(|r| r.area() > min_area).collect()
}
pub fn circle_inscribed_in_rectangle(rect: &Rectangle) -> Circle {
let radius = rect.width.min(rect.height) / 2.0;
Circle::new(radius)
}
pub fn rectangle_circumscribed_around_circle(circle: &Circle) -> Rectangle {
let side = circle.diameter();
Rectangle::new(side, side)
}
// 计算多边形的重心(质心)
pub fn centroid_of_triangles(triangles: &[Triangle]) -> (f64, f64) {
if triangles.is_empty() {
return (0.0, 0.0);
}
let total_area: f64 = triangles.iter().map(|t| t.area()).sum();
if total_area == 0.0 {
return (0.0, 0.0);
}
// 简化计算,假设所有三角形都在原点附近
let weighted_x: f64 = triangles.iter().enumerate()
.map(|(i, t)| (i as f64) * t.area())
.sum();
let weighted_y: f64 = triangles.iter().enumerate()
.map(|(i, t)| (i as f64) * t.area())
.sum();
(weighted_x / total_area, weighted_y / total_area)
}
// utils/mod.rs - 工具模块入口
pub mod formatter;
pub mod validator;
// 重新导出常用功能
pub use formatter::format_number;
pub use validator::{validate_email, validate_phone};
// utils/formatter.rs - 格式化工具
use std::fmt;
pub fn format_number(num: f64) -> String {
format_with_separator(num, ",")
}
pub fn format_with_separator(num: f64, separator: &str) -> String {
let parts: Vec<&str> = num.to_string().split('.').collect();
let integer_part = parts[0];
let decimal_part = if parts.len() > 1 { parts[1] } else { "" };
let formatted_integer = add_thousand_separators(integer_part, separator);
if decimal_part.is_empty() {
formatted_integer
} else {
format!("{}.{}", formatted_integer, decimal_part)
}
}
fn add_thousand_separators(s: &str, separator: &str) -> String {
let chars: Vec<char> = s.chars().collect();
let mut result = String::new();
for (i, &ch) in chars.iter().enumerate() {
if i > 0 && (chars.len() - i) % 3 == 0 {
result.push_str(separator);
}
result.push(ch);
}
result
}
pub fn format_currency(amount: f64, currency: &str) -> String {
format!("{} {:.2}", currency, amount)
}
pub fn format_percentage(value: f64) -> String {
format!("{:.1}%", value * 100.0)
}
pub fn format_file_size(bytes: u64) -> String {
const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
let mut size = bytes as f64;
let mut unit_index = 0;
while size >= 1024.0 && unit_index < UNITS.len() - 1 {
size /= 1024.0;
unit_index += 1;
}
if unit_index == 0 {
format!("{} {}", bytes, UNITS[unit_index])
} else {
format!("{:.1} {}", size, UNITS[unit_index])
}
}
// 自定义格式化结构体
pub struct CustomFormatter {
pub decimal_places: usize,
pub thousand_separator: String,
pub decimal_separator: String,
}
impl CustomFormatter {
pub fn new() -> Self {
CustomFormatter {
decimal_places: 2,
thousand_separator: ",".to_string(),
decimal_separator: ".".to_string(),
}
}
pub fn format(&self, num: f64) -> String {
let rounded = (num * 10_f64.powi(self.decimal_places as i32)).round()
/ 10_f64.powi(self.decimal_places as i32);
let formatted = format!("{:.prec$}", rounded, prec = self.decimal_places);
// 替换小数点分隔符
let with_decimal_sep = formatted.replace('.', &self.decimal_separator);
// 添加千位分隔符
if let Some(decimal_pos) = with_decimal_sep.find(&self.decimal_separator) {
let integer_part = &with_decimal_sep[..decimal_pos];
let decimal_part = &with_decimal_sep[decimal_pos..];
format!("{}{}",
add_thousand_separators(integer_part, &self.thousand_separator),
decimal_part)
} else {
add_thousand_separators(&with_decimal_sep, &self.thousand_separator)
}
}
}
impl Default for CustomFormatter {
fn default() -> Self {
Self::new()
}
}
// utils/validator.rs - 验证工具
use std::collections::HashSet;
pub fn validate_email(email: &str) -> bool {
// 简单的邮箱验证
email.contains('@') &&
email.contains('.') &&
!email.starts_with('@') &&
!email.ends_with('@') &&
!email.starts_with('.') &&
!email.ends_with('.')
}
pub fn validate_phone(phone: &str) -> bool {
// 简单的电话号码验证(只允许数字、空格、短横线、括号)
phone.chars().all(|c| c.is_ascii_digit() || " -().".contains(c)) &&
phone.chars().any(|c| c.is_ascii_digit())
}
pub fn validate_password_strength(password: &str) -> PasswordStrength {
let mut score = 0;
let mut feedback = Vec::new();
if password.len() >= 8 {
score += 1;
} else {
feedback.push("密码长度至少8位".to_string());
}
if password.chars().any(|c| c.is_ascii_lowercase()) {
score += 1;
} else {
feedback.push("需要包含小写字母".to_string());
}
if password.chars().any(|c| c.is_ascii_uppercase()) {
score += 1;
} else {
feedback.push("需要包含大写字母".to_string());
}
if password.chars().any(|c| c.is_ascii_digit()) {
score += 1;
} else {
feedback.push("需要包含数字".to_string());
}
if password.chars().any(|c| "!@#$%^&*()_+-=[]{}|;:,.<>?".contains(c)) {
score += 1;
} else {
feedback.push("需要包含特殊字符".to_string());
}
let strength = match score {
0..=1 => Strength::Weak,
2..=3 => Strength::Medium,
4..=5 => Strength::Strong,
_ => Strength::Strong,
};
PasswordStrength {
strength,
score,
feedback,
}
}
#[derive(Debug, Clone)]
pub enum Strength {
Weak,
Medium,
Strong,
}
#[derive(Debug, Clone)]
pub struct PasswordStrength {
pub strength: Strength,
pub score: i32,
pub feedback: Vec<String>,
}
pub fn validate_url(url: &str) -> bool {
url.starts_with("http://") || url.starts_with("https://")
}
pub fn validate_ip_address(ip: &str) -> bool {
let parts: Vec<&str> = ip.split('.').collect();
if parts.len() != 4 {
return false;
}
for part in parts {
if let Ok(num) = part.parse::<u8>() {
if part.len() > 1 && part.starts_with('0') {
return false; // 不允许前导零
}
} else {
return false;
}
}
true
}
pub fn validate_credit_card(card_number: &str) -> bool {
// Luhn算法验证信用卡号
let digits: Vec<u32> = card_number
.chars()
.filter(|c| c.is_ascii_digit())
.map(|c| c.to_digit(10).unwrap())
.collect();
if digits.len() < 13 || digits.len() > 19 {
return false;
}
let mut sum = 0;
let mut alternate = false;
for &digit in digits.iter().rev() {
let mut n = digit;
if alternate {
n *= 2;
if n > 9 {
n = (n / 10) + (n % 10);
}
}
sum += n;
alternate = !alternate;
}
sum % 10 == 0
}
// 数据清理函数
pub fn sanitize_input(input: &str) -> String {
input
.trim()
.replace("<", "<")
.replace(">", ">")
.replace("&", "&")
.replace("\"", """)
.replace("'", "'")
}
pub fn remove_duplicates<T: Clone + std::hash::Hash + Eq>(items: Vec<T>) -> Vec<T> {
let mut seen = HashSet::new();
let mut result = Vec::new();
for item in items {
if seen.insert(item.clone()) {
result.push(item);
}
}
result
}
rustc main.rs && ./main
7.3 包和Crate管理
7.3.1 创建和使用包
[package]
name = "package_demo"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }
rand = "0.8"
clap = { version = "4.0", features = ["derive"] }
[dev-dependencies]
tokio-test = "0.4"
[[bin]]
name = "main"
path = "src/main.rs"
[[bin]]
name = "cli"
path = "src/bin/cli.rs"
[lib]
name = "package_demo"
path = "src/lib.rs"
// src/lib.rs - 库的根文件
pub mod models;
pub mod services;
pub mod utils;
// 重新导出主要的公共API
pub use models::{User, Task, TaskStatus};
pub use services::{UserService, TaskService};
pub use utils::{generate_id, current_timestamp};
// 库的版本信息
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const NAME: &str = env!("CARGO_PKG_NAME");
// 库的初始化函数
pub fn init() {
println!("初始化 {} v{}", NAME, VERSION);
}
// 错误类型定义
#[derive(Debug, Clone)]
pub enum LibError {
InvalidInput(String),
NotFound(String),
InternalError(String),
}
impl std::fmt::Display for LibError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
LibError::InvalidInput(msg) => write!(f, "输入错误: {}", msg),
LibError::NotFound(msg) => write!(f, "未找到: {}", msg),
LibError::InternalError(msg) => write!(f, "内部错误: {}", msg),
}
}
}
impl std::error::Error for LibError {}
// 结果类型别名
pub type Result<T> = std::result::Result<T, LibError>;
// src/models.rs - 数据模型
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: String,
pub username: String,
pub email: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl User {
pub fn new(username: String, email: String) -> Self {
let now = Utc::now();
User {
id: crate::utils::generate_id(),
username,
email,
created_at: now,
updated_at: now,
}
}
pub fn update_email(&mut self, new_email: String) {
self.email = new_email;
self.updated_at = Utc::now();
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskStatus {
Pending,
InProgress,
Completed,
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Task {
pub id: String,
pub title: String,
pub description: String,
pub status: TaskStatus,
pub user_id: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub due_date: Option<DateTime<Utc>>,
}
impl Task {
pub fn new(title: String, description: String, user_id: String) -> Self {
let now = Utc::now();
Task {
id: crate::utils::generate_id(),
title,
description,
status: TaskStatus::Pending,
user_id,
created_at: now,
updated_at: now,
due_date: None,
}
}
pub fn set_status(&mut self, status: TaskStatus) {
self.status = status;
self.updated_at = Utc::now();
}
pub fn set_due_date(&mut self, due_date: DateTime<Utc>) {
self.due_date = Some(due_date);
self.updated_at = Utc::now();
}
pub fn is_overdue(&self) -> bool {
if let Some(due_date) = self.due_date {
Utc::now() > due_date && !matches!(self.status, TaskStatus::Completed)
} else {
false
}
}
}
// src/services.rs - 业务逻辑服务
use std::collections::HashMap;
use crate::{User, Task, TaskStatus, Result, LibError};
pub struct UserService {
users: HashMap<String, User>,
}
impl UserService {
pub fn new() -> Self {
UserService {
users: HashMap::new(),
}
}
pub fn create_user(&mut self, username: String, email: String) -> Result<User> {
// 验证用户名唯一性
if self.users.values().any(|u| u.username == username) {
return Err(LibError::InvalidInput("用户名已存在".to_string()));
}
// 验证邮箱唯一性
if self.users.values().any(|u| u.email == email) {
return Err(LibError::InvalidInput("邮箱已存在".to_string()));
}
let user = User::new(username, email);
let user_id = user.id.clone();
self.users.insert(user_id, user.clone());
Ok(user)
}
pub fn get_user(&self, user_id: &str) -> Result<&User> {
self.users.get(user_id)
.ok_or_else(|| LibError::NotFound(format!("用户 {} 不存在", user_id)))
}
pub fn update_user_email(&mut self, user_id: &str, new_email: String) -> Result<()> {
// 检查邮箱是否已被其他用户使用
if self.users.values().any(|u| u.id != user_id && u.email == new_email) {
return Err(LibError::InvalidInput("邮箱已被使用".to_string()));
}
let user = self.users.get_mut(user_id)
.ok_or_else(|| LibError::NotFound(format!("用户 {} 不存在", user_id)))?;
user.update_email(new_email);
Ok(())
}
pub fn delete_user(&mut self, user_id: &str) -> Result<User> {
self.users.remove(user_id)
.ok_or_else(|| LibError::NotFound(format!("用户 {} 不存在", user_id)))
}
pub fn list_users(&self) -> Vec<&User> {
self.users.values().collect()
}
pub fn find_user_by_username(&self, username: &str) -> Option<&User> {
self.users.values().find(|u| u.username == username)
}
pub fn find_user_by_email(&self, email: &str) -> Option<&User> {
self.users.values().find(|u| u.email == email)
}
}
impl Default for UserService {
fn default() -> Self {
Self::new()
}
}
pub struct TaskService {
tasks: HashMap<String, Task>,
}
impl TaskService {
pub fn new() -> Self {
TaskService {
tasks: HashMap::new(),
}
}
pub fn create_task(&mut self, title: String, description: String, user_id: String) -> Result<Task> {
if title.trim().is_empty() {
return Err(LibError::InvalidInput("任务标题不能为空".to_string()));
}
let task = Task::new(title, description, user_id);
let task_id = task.id.clone();
self.tasks.insert(task_id, task.clone());
Ok(task)
}
pub fn get_task(&self, task_id: &str) -> Result<&Task> {
self.tasks.get(task_id)
.ok_or_else(|| LibError::NotFound(format!("任务 {} 不存在", task_id)))
}
pub fn update_task_status(&mut self, task_id: &str, status: TaskStatus) -> Result<()> {
let task = self.tasks.get_mut(task_id)
.ok_or_else(|| LibError::NotFound(format!("任务 {} 不存在", task_id)))?;
task.set_status(status);
Ok(())
}
pub fn delete_task(&mut self, task_id: &str) -> Result<Task> {
self.tasks.remove(task_id)
.ok_or_else(|| LibError::NotFound(format!("任务 {} 不存在", task_id)))
}
pub fn list_tasks(&self) -> Vec<&Task> {
self.tasks.values().collect()
}
pub fn list_tasks_by_user(&self, user_id: &str) -> Vec<&Task> {
self.tasks.values()
.filter(|t| t.user_id == user_id)
.collect()
}
pub fn list_tasks_by_status(&self, status: &TaskStatus) -> Vec<&Task> {
self.tasks.values()
.filter(|t| std::mem::discriminant(&t.status) == std::mem::discriminant(status))
.collect()
}
pub fn list_overdue_tasks(&self) -> Vec<&Task> {
self.tasks.values()
.filter(|t| t.is_overdue())
.collect()
}
pub fn get_task_statistics(&self) -> TaskStatistics {
let total = self.tasks.len();
let pending = self.list_tasks_by_status(&TaskStatus::Pending).len();
let in_progress = self.list_tasks_by_status(&TaskStatus::InProgress).len();
let completed = self.list_tasks_by_status(&TaskStatus::Completed).len();
let cancelled = self.list_tasks_by_status(&TaskStatus::Cancelled).len();
let overdue = self.list_overdue_tasks().len();
TaskStatistics {
total,
pending,
in_progress,
completed,
cancelled,
overdue,
}
}
}
impl Default for TaskService {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct TaskStatistics {
pub total: usize,
pub pending: usize,
pub in_progress: usize,
pub completed: usize,
pub cancelled: usize,
pub overdue: usize,
}
// src/utils.rs - 工具函数
use rand::Rng;
use chrono::{DateTime, Utc};
pub fn generate_id() -> String {
let mut rng = rand::thread_rng();
let id: u64 = rng.gen();
format!("{:016x}", id)
}
pub fn current_timestamp() -> DateTime<Utc> {
Utc::now()
}
pub fn format_duration(seconds: i64) -> String {
let days = seconds / 86400;
let hours = (seconds % 86400) / 3600;
let minutes = (seconds % 3600) / 60;
let secs = seconds % 60;
if days > 0 {
format!("{}天 {}小时 {}分钟", days, hours, minutes)
} else if hours > 0 {
format!("{}小时 {}分钟", hours, minutes)
} else if minutes > 0 {
format!("{}分钟 {}秒", minutes, secs)
} else {
format!("{}秒", secs)
}
}
pub fn validate_email(email: &str) -> bool {
email.contains('@') &&
email.contains('.') &&
!email.starts_with('@') &&
!email.ends_with('@')
}
pub fn sanitize_string(input: &str) -> String {
input.trim()
.replace("<", "<")
.replace(">", ">")
.replace("&", "&")
}
// 分页辅助函数
pub fn paginate<T>(items: &[T], page: usize, page_size: usize) -> &[T] {
let start = page * page_size;
let end = std::cmp::min(start + page_size, items.len());
if start >= items.len() {
&[]
} else {
&items[start..end]
}
}
#[derive(Debug, Clone)]
pub struct PaginationInfo {
pub current_page: usize,
pub page_size: usize,
pub total_items: usize,
pub total_pages: usize,
pub has_next: bool,
pub has_previous: bool,
}
impl PaginationInfo {
pub fn new(current_page: usize, page_size: usize, total_items: usize) -> Self {
let total_pages = (total_items + page_size - 1) / page_size;
PaginationInfo {
current_page,
page_size,
total_items,
total_pages,
has_next: current_page + 1 < total_pages,
has_previous: current_page > 0,
}
}
}
// src/main.rs - 主程序
use package_demo::*;
use chrono::Utc;
fn main() {
println!("📦 包管理演示");
println!("============");
// 初始化库
package_demo::init();
demonstrate_user_service();
demonstrate_task_service();
demonstrate_integration();
}
fn demonstrate_user_service() {
println!("\n用户服务演示:");
let mut user_service = UserService::new();
// 创建用户
match user_service.create_user("alice".to_string(), "alice@example.com".to_string()) {
Ok(user) => println!("创建用户成功: {:?}", user),
Err(e) => println!("创建用户失败: {}", e),
}
match user_service.create_user("bob".to_string(), "bob@example.com".to_string()) {
Ok(user) => println!("创建用户成功: {:?}", user),
Err(e) => println!("创建用户失败: {}", e),
}
// 尝试创建重复用户名
match user_service.create_user("alice".to_string(), "alice2@example.com".to_string()) {
Ok(user) => println!("创建用户成功: {:?}", user),
Err(e) => println!("创建用户失败: {}", e),
}
// 列出所有用户
println!("\n所有用户:");
for user in user_service.list_users() {
println!(" - {}: {} ({})", user.username, user.email, user.id);
}
// 查找用户
if let Some(user) = user_service.find_user_by_username("alice") {
println!("\n找到用户 alice: {}", user.email);
// 更新邮箱
match user_service.update_user_email(&user.id, "alice.new@example.com".to_string()) {
Ok(()) => println!("邮箱更新成功"),
Err(e) => println!("邮箱更新失败: {}", e),
}
}
}
fn demonstrate_task_service() {
println!("\n任务服务演示:");
let mut task_service = TaskService::new();
let user_id = generate_id();
// 创建任务
let tasks_data = vec![
("学习Rust", "完成Rust教程的学习"),
("写代码", "实现一个小项目"),
("测试", "编写单元测试"),
];
let mut task_ids = Vec::new();
for (title, description) in tasks_data {
match task_service.create_task(title.to_string(), description.to_string(), user_id.clone()) {
Ok(task) => {
println!("创建任务成功: {}", task.title);
task_ids.push(task.id);
}
Err(e) => println!("创建任务失败: {}", e),
}
}
// 更新任务状态
if let Some(task_id) = task_ids.first() {
match task_service.update_task_status(task_id, TaskStatus::InProgress) {
Ok(()) => println!("任务状态更新成功"),
Err(e) => println!("任务状态更新失败: {}", e),
}
}
if let Some(task_id) = task_ids.get(2) {
match task_service.update_task_status(task_id, TaskStatus::Completed) {
Ok(()) => println!("任务状态更新成功"),
Err(e) => println!("任务状态更新失败: {}", e),
}
}
// 显示任务统计
let stats = task_service.get_task_statistics();
println!("\n任务统计:");
println!(" 总计: {}", stats.total);
println!(" 待处理: {}", stats.pending);
println!(" 进行中: {}", stats.in_progress);
println!(" 已完成: {}", stats.completed);
println!(" 已取消: {}", stats.cancelled);
println!(" 逾期: {}", stats.overdue);
// 列出用户的任务
println!("\n用户任务:");
for task in task_service.list_tasks_by_user(&user_id) {
println!(" - {}: {:?}", task.title, task.status);
}
}
fn demonstrate_integration() {
println!("\n集成演示:");
let mut user_service = UserService::new();
let mut task_service = TaskService::new();
// 创建用户和任务的完整工作流
let user = user_service.create_user("charlie".to_string(), "charlie@example.com".to_string())
.expect("创建用户失败");
println!("创建用户: {}", user.username);
// 为用户创建多个任务
let task_titles = vec!["任务1", "任务2", "任务3", "任务4", "任务5"];
for title in task_titles {
let _ = task_service.create_task(
title.to_string(),
format!("{} 的描述", title),
user.id.clone(),
);
}
// 模拟任务进度
let user_tasks = task_service.list_tasks_by_user(&user.id);
println!("\n用户 {} 的任务进度:", user.username);
for (i, task) in user_tasks.iter().enumerate() {
let status = match i {
0 => TaskStatus::Completed,
1 => TaskStatus::InProgress,
2 => TaskStatus::InProgress,
_ => TaskStatus::Pending,
};
let _ = task_service.update_task_status(&task.id, status.clone());
println!(" - {}: {:?}", task.title, status);
}
// 最终统计
let final_stats = task_service.get_task_statistics();
println!("\n最终统计:");
println!(" 总任务数: {}", final_stats.total);
println!(" 完成率: {:.1}%",
(final_stats.completed as f64 / final_stats.total as f64) * 100.0);
}
// src/bin/cli.rs - 命令行工具
use clap::{Parser, Subcommand};
use package_demo::*;
#[derive(Parser)]
#[command(name = "task-manager")]
#[command(about = "一个简单的任务管理CLI工具")]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// 创建新用户
CreateUser {
/// 用户名
username: String,
/// 邮箱地址
email: String,
},
/// 列出所有用户
ListUsers,
/// 创建新任务
CreateTask {
/// 任务标题
title: String,
/// 任务描述
description: String,
/// 用户ID
user_id: String,
},
/// 列出任务
ListTasks {
/// 可选的用户ID过滤
#[arg(short, long)]
user_id: Option<String>,
/// 可选的状态过滤
#[arg(short, long)]
status: Option<String>,
},
/// 更新任务状态
UpdateTask {
/// 任务ID
task_id: String,
/// 新状态
status: String,
},
/// 显示统计信息
Stats,
}
fn main() {
let cli = Cli::parse();
let mut user_service = UserService::new();
let mut task_service = TaskService::new();
match cli.command {
Commands::CreateUser { username, email } => {
match user_service.create_user(username.clone(), email) {
Ok(user) => println!("✅ 用户创建成功: {} (ID: {})", username, user.id),
Err(e) => eprintln!("❌ 创建用户失败: {}", e),
}
}
Commands::ListUsers => {
let users = user_service.list_users();
if users.is_empty() {
println!("📭 没有找到用户");
} else {
println!("👥 用户列表:");
for user in users {
println!(" - {} ({}) - {}", user.username, user.id, user.email);
}
}
}
Commands::CreateTask { title, description, user_id } => {
match task_service.create_task(title.clone(), description, user_id) {
Ok(task) => println!("✅ 任务创建成功: {} (ID: {})", title, task.id),
Err(e) => eprintln!("❌ 创建任务失败: {}", e),
}
}
Commands::ListTasks { user_id, status } => {
let mut tasks = task_service.list_tasks();
// 按用户ID过滤
if let Some(uid) = user_id {
tasks = task_service.list_tasks_by_user(&uid);
}
// 按状态过滤
if let Some(status_str) = status {
let filter_status = match status_str.to_lowercase().as_str() {
"pending" => Some(TaskStatus::Pending),
"inprogress" | "in_progress" => Some(TaskStatus::InProgress),
"completed" => Some(TaskStatus::Completed),
"cancelled" => Some(TaskStatus::Cancelled),
_ => {
eprintln!("❌ 无效的状态: {}", status_str);
return;
}
};
if let Some(status) = filter_status {
tasks = task_service.list_tasks_by_status(&status);
}
}
if tasks.is_empty() {
println!("📭 没有找到任务");
} else {
println!("📋 任务列表:");
for task in tasks {
println!(" - {} ({}) - {:?} - 用户: {}",
task.title, task.id, task.status, task.user_id);
}
}
}
Commands::UpdateTask { task_id, status } => {
let new_status = match status.to_lowercase().as_str() {
"pending" => TaskStatus::Pending,
"inprogress" | "in_progress" => TaskStatus::InProgress,
"completed" => TaskStatus::Completed,
"cancelled" => TaskStatus::Cancelled,
_ => {
eprintln!("❌ 无效的状态: {}", status);
return;
}
};
match task_service.update_task_status(&task_id, new_status) {
Ok(()) => println!("✅ 任务状态更新成功"),
Err(e) => eprintln!("❌ 更新任务状态失败: {}", e),
}
}
Commands::Stats => {
let stats = task_service.get_task_statistics();
let users = user_service.list_users();
println!("📊 统计信息:");
println!(" 用户总数: {}", users.len());
println!(" 任务总数: {}", stats.total);
println!(" 待处理: {}", stats.pending);
println!(" 进行中: {}", stats.in_progress);
println!(" 已完成: {}", stats.completed);
println!(" 已取消: {}", stats.cancelled);
println!(" 逾期: {}", stats.overdue);
if stats.total > 0 {
let completion_rate = (stats.completed as f64 / stats.total as f64) * 100.0;
println!(" 完成率: {:.1}%", completion_rate);
}
}
}
}
cd package_demo
cargo build
cargo run --bin cli -- --help
cargo run --bin cli -- create-user alice alice@example.com
cargo run --bin cli -- list-users
cargo run --bin cli -- stats
7.4 外部依赖和Crate使用
7.4.1 使用外部Crate
use serde::{Deserialize, Serialize};
use serde_json;
use chrono::{DateTime, Utc, Duration};
use rand::Rng;
use std::collections::HashMap;
fn main() {
println!("🔗 外部依赖演示");
println!("===============");
demonstrate_serde();
demonstrate_chrono();
demonstrate_rand();
demonstrate_combined_usage();
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Person {
name: String,
age: u32,
email: String,
created_at: DateTime<Utc>,
tags: Vec<String>,
metadata: HashMap<String, String>,
}
impl Person {
fn new(name: String, age: u32, email: String) -> Self {
Person {
name,
age,
email,
created_at: Utc::now(),
tags: Vec::new(),
metadata: HashMap::new(),
}
}
fn add_tag(&mut self, tag: String) {
if !self.tags.contains(&tag) {
self.tags.push(tag);
}
}
fn set_metadata(&mut self, key: String, value: String) {
self.metadata.insert(key, value);
}
}
fn demonstrate_serde() {
println!("\nSerde序列化演示:");
let mut person = Person::new(
"张三".to_string(),
25,
"zhangsan@example.com".to_string(),
);
person.add_tag("开发者".to_string());
person.add_tag("Rust爱好者".to_string());
person.set_metadata("部门".to_string(), "技术部".to_string());
person.set_metadata("级别".to_string(), "高级".to_string());
// 序列化为JSON
match serde_json::to_string_pretty(&person) {
Ok(json) => {
println!("序列化结果:");
println!("{}", json);
// 反序列化
match serde_json::from_str::<Person>(&json) {
Ok(deserialized) => {
println!("\n反序列化成功:");
println!("姓名: {}, 年龄: {}, 邮箱: {}",
deserialized.name, deserialized.age, deserialized.email);
println!("标签: {:?}", deserialized.tags);
println!("元数据: {:?}", deserialized.metadata);
}
Err(e) => println!("反序列化失败: {}", e),
}
}
Err(e) => println!("序列化失败: {}", e),
}
}
fn demonstrate_chrono() {
println!("\nChrono时间处理演示:");
let now = Utc::now();
println!("当前时间: {}", now.format("%Y-%m-%d %H:%M:%S UTC"));
// 时间计算
let one_week_later = now + Duration::weeks(1);
let one_month_ago = now - Duration::days(30);
println!("一周后: {}", one_week_later.format("%Y-%m-%d %H:%M:%S UTC"));
println!("一个月前: {}", one_month_ago.format("%Y-%m-%d %H:%M:%S UTC"));
// 时间解析
let date_str = "2024-01-15T10:30:00Z";
match date_str.parse::<DateTime<Utc>>() {
Ok(parsed_date) => {
println!("解析时间: {}", parsed_date.format("%Y年%m月%d日 %H:%M:%S"));
let duration_since = now.signed_duration_since(parsed_date);
println!("距离现在: {}天", duration_since.num_days());
}
Err(e) => println!("时间解析失败: {}", e),
}
// 时间戳
let timestamp = now.timestamp();
let timestamp_millis = now.timestamp_millis();
println!("时间戳(秒): {}", timestamp);
println!("时间戳(毫秒): {}", timestamp_millis);
}
fn demonstrate_rand() {
println!("\nRand随机数演示:");
let mut rng = rand::thread_rng();
// 生成随机数
let random_int: i32 = rng.gen_range(1..=100);
let random_float: f64 = rng.gen_range(0.0..1.0);
let random_bool: bool = rng.gen();
println!("随机整数(1-100): {}", random_int);
println!("随机浮点数(0-1): {:.4}", random_float);
println!("随机布尔值: {}", random_bool);
// 随机选择
let colors = vec!["红色", "绿色", "蓝色", "黄色", "紫色"];
let random_color = colors[rng.gen_range(0..colors.len())];
println!("随机颜色: {}", random_color);
// 生成随机字符串
let random_string: String = (0..8)
.map(|_| {
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
chars.chars().nth(rng.gen_range(0..chars.len())).unwrap()
})
.collect();
println!("随机字符串: {}", random_string);
// 随机UUID风格的ID
let random_id = format!("{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
rng.gen::<u32>(),
rng.gen::<u16>(),
rng.gen::<u16>(),
rng.gen::<u16>(),
rng.gen::<u64>() & 0xffffffffffff);
println!("随机ID: {}", random_id);
}
fn demonstrate_combined_usage() {
println!("\n综合使用演示:");
let mut rng = rand::thread_rng();
let mut people = Vec::new();
// 生成随机人员数据
let names = vec!["张三", "李四", "王五", "赵六", "钱七"];
let domains = vec!["example.com", "test.org", "demo.net"];
let departments = vec!["技术部", "产品部", "运营部", "市场部"];
let levels = vec!["初级", "中级", "高级", "专家"];
for i in 0..5 {
let name = names[i].to_string();
let age = rng.gen_range(22..=45);
let domain = domains[rng.gen_range(0..domains.len())];
let email = format!("{}@{}",
name.chars().collect::<Vec<_>>().iter().collect::<String>().to_lowercase(),
domain);
let mut person = Person::new(name, age, email);
// 随机添加标签
let tags = vec!["开发者", "设计师", "产品经理", "测试工程师", "运维工程师"];
let tag_count = rng.gen_range(1..=3);
for _ in 0..tag_count {
let tag = tags[rng.gen_range(0..tags.len())].to_string();
person.add_tag(tag);
}
// 添加元数据
let department = departments[rng.gen_range(0..departments.len())].to_string();
let level = levels[rng.gen_range(0..levels.len())].to_string();
person.set_metadata("部门".to_string(), department);
person.set_metadata("级别".to_string(), level);
person.set_metadata("入职时间".to_string(),
(Utc::now() - Duration::days(rng.gen_range(30..=1000)))
.format("%Y-%m-%d").to_string());
people.push(person);
}
// 序列化整个数据集
match serde_json::to_string_pretty(&people) {
Ok(json) => {
println!("生成的人员数据:");
println!("{}", json);
// 统计信息
let total_age: u32 = people.iter().map(|p| p.age).sum();
let avg_age = total_age as f64 / people.len() as f64;
let mut department_count = HashMap::new();
for person in &people {
if let Some(dept) = person.metadata.get("部门") {
*department_count.entry(dept.clone()).or_insert(0) += 1;
}
}
println!("\n统计信息:");
println!("总人数: {}", people.len());
println!("平均年龄: {:.1}岁", avg_age);
println!("部门分布:");
for (dept, count) in department_count {
println!(" {}: {}人", dept, count);
}
}
Err(e) => println!("序列化失败: {}", e),
}
}
rustc external_deps_demo.rs && ./external_deps_demo
7.4.2 工作空间管理
[workspace]
members = [
"core",
"web",
"cli",
"utils",
]
[workspace.dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"] }
tokio = { version = "1.0", features = ["full"] }
clap = { version = "4.0", features = ["derive"] }
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
panic = "abort"
[package]
name = "core"
version = "0.1.0"
edition = "2021"
[dependencies]
serde.workspace = true
serde_json.workspace = true
chrono.workspace = true
// core/src/lib.rs - 核心业务逻辑
pub mod models;
pub mod services;
pub mod errors;
pub use models::*;
pub use services::*;
pub use errors::*;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
[package]
name = "utils"
version = "0.1.0"
edition = "2021"
[dependencies]
chrono.workspace = true
serde.workspace = true
// utils/src/lib.rs - 通用工具
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
pub fn generate_id() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
format!("{:x}", timestamp)
}
pub fn current_timestamp() -> DateTime<Utc> {
Utc::now()
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiResponse<T> {
pub success: bool,
pub data: Option<T>,
pub message: String,
pub timestamp: DateTime<Utc>,
}
impl<T> ApiResponse<T> {
pub fn success(data: T) -> Self {
ApiResponse {
success: true,
data: Some(data),
message: "操作成功".to_string(),
timestamp: current_timestamp(),
}
}
pub fn error(message: String) -> Self {
ApiResponse {
success: false,
data: None,
message,
timestamp: current_timestamp(),
}
}
}
[package]
name = "web"
version = "0.1.0"
edition = "2021"
[dependencies]
core = { path = "../core" }
utils = { path = "../utils" }
tokio.workspace = true
serde.workspace = true
serde_json.workspace = true
[package]
name = "cli"
version = "0.1.0"
edition = "2021"
[dependencies]
core = { path = "../core" }
utils = { path = "../utils" }
clap.workspace = true
serde_json.workspace = true
cd workspace_demo
cargo build
cargo test
cargo build --release
7.5 模块系统最佳实践
7.5.1 项目结构建议
// 推荐的项目结构示例
/*
项目根目录/
├── Cargo.toml # 项目配置
├── README.md # 项目说明
├── src/ # 源代码目录
│ ├── main.rs # 二进制程序入口
│ ├── lib.rs # 库入口(如果是库项目)
│ ├── models/ # 数据模型
│ │ ├── mod.rs
│ │ ├── user.rs
│ │ └── task.rs
│ ├── services/ # 业务逻辑
│ │ ├── mod.rs
│ │ ├── user_service.rs
│ │ └── task_service.rs
│ ├── handlers/ # 请求处理器
│ │ ├── mod.rs
│ │ ├── user_handler.rs
│ │ └── task_handler.rs
│ ├── utils/ # 工具函数
│ │ ├── mod.rs
│ │ ├── validation.rs
│ │ └── formatting.rs
│ ├── config/ # 配置管理
│ │ ├── mod.rs
│ │ └── settings.rs
│ └── errors/ # 错误定义
│ ├── mod.rs
│ └── app_error.rs
├── tests/ # 集成测试
│ ├── common/
│ │ └── mod.rs
│ ├── user_tests.rs
│ └── task_tests.rs
├── benches/ # 性能测试
│ └── benchmarks.rs
├── examples/ # 示例代码
│ └── basic_usage.rs
└── docs/ # 文档
└── api.md
*/
fn main() {
println!("📁 项目结构最佳实践");
println!("==================");
demonstrate_naming_conventions();
demonstrate_visibility_guidelines();
demonstrate_module_organization();
}
fn demonstrate_naming_conventions() {
println!("\n命名约定:");
println!("- 模块名: snake_case (user_service, task_manager)");
println!("- 文件名: snake_case (user_service.rs, task_manager.rs)");
println!("- 结构体: PascalCase (User, TaskManager)");
println!("- 函数: snake_case (create_user, get_task_by_id)");
println!("- 常量: SCREAMING_SNAKE_CASE (MAX_USERS, DEFAULT_TIMEOUT)");
println!("- 枚举: PascalCase (TaskStatus, UserRole)");
println!("- 枚举变体: PascalCase (Pending, InProgress)");
}
fn demonstrate_visibility_guidelines() {
println!("\n可见性指导原则:");
println!("- 默认私有: 只有需要对外暴露的才使用pub");
println!("- pub(crate): 整个crate内可见,适用于内部API");
println!("- pub(super): 父模块可见,适用于模块间协作");
println!("- pub(in path): 指定路径内可见,精确控制范围");
println!("- 结构体字段: 谨慎公开,优先提供方法访问");
}
fn demonstrate_module_organization() {
println!("\n模块组织原则:");
println!("- 单一职责: 每个模块专注一个功能领域");
println!("- 层次清晰: 按功能和抽象层次组织");
println!("- 依赖方向: 高层模块依赖低层模块");
println!("- 重新导出: 在mod.rs中重新导出常用类型");
println!("- 文档完整: 为公共API提供文档注释");
}
rustc project_structure_example.rs && ./project_structure_example
本章小结
在本章中,我们深入学习了Rust的模块系统,这是组织和管理Rust代码的核心机制:
🎯 核心概念
- 模块定义: 使用
mod关键字定义模块,组织相关功能 - 可见性控制: 通过
pub、pub(crate)、pub(super)等控制访问权限 - 文件模块: 将模块分离到独立文件,提高代码可维护性
- 包和Crate: 理解Rust的包管理和依赖系统
🔧 实用技能
- 模块路径: 掌握绝对路径、相对路径和
use语句的使用 - 重新导出: 使用
pub use简化API接口 - 工作空间: 管理多个相关的包和项目
- 外部依赖: 集成和使用第三方Crate
📋 最佳实践
- 命名约定: 遵循Rust社区的命名规范
- 项目结构: 按功能和层次组织代码
- 可见性原则: 最小化公共接口,保护内部实现
- 文档化: 为公共API提供清晰的文档
🚀 下一章预告
下一章我们将学习错误处理,包括:
- Result和Option类型的深入使用
- 错误传播和处理策略
- 自定义错误类型
- 错误处理的最佳实践
💡 练习题
- 模块重构: 将一个大型的单文件程序重构为多模块结构
- 可见性设计: 设计一个库的公共API,合理控制可见性
- 工作空间项目: 创建一个包含多个相关包的工作空间
- 依赖管理: 集成多个外部Crate构建一个完整应用
- 文档编写: 为你的模块编写完整的API文档
通过本章的学习,你应该能够熟练使用Rust的模块系统来组织和管理复杂的项目结构!