第8章 模塊系統_#android

文章目錄

  • 第8章 模塊系統
  • 8.1 包、crate和模塊
  • Rust代碼組織的基本概念
  • 包(Packages)
  • Crate
  • 模塊(Modules)
  • 創建和使用模塊
  • 基本模塊定義
  • 模塊的可見性
  • 模塊的層次結構
  • 模塊作為接口設計工具
  • 實戰:配置管理系統
  • 8.2 路徑與作用域
  • 路徑的概念
  • 路徑示例
  • 使用super進行相對路徑訪問
  • 結構體字段的可見性
  • 實戰:權限系統
  • 8.3 use關鍵字與重導出
  • 使用use引入路徑
  • 使用use引入函數
  • 使用use引入結構體和枚舉
  • 重導出(Re-exporting)
  • 使用as關鍵字重命名
  • 嵌套路徑
  • 通配符導入
  • 實戰:日誌系統
  • 8.4 文件組織與模塊拆分
  • 將模塊拆分為文件
  • 基本文件拆分
  • 子目錄中的模塊
  • 使用mod.rs文件(舊風格)
  • 實戰:完整的Web應用結構
  • 測試模塊組織
  • 最佳實踐總結
  • 模塊設計最佳實踐
  • 文件組織最佳實踐
  • use關鍵字最佳實踐
  • 測試組織最佳實踐

第8章 模塊系統

隨着Rust項目的不斷增長,良好的代碼組織變得至關重要。Rust提供了一套強大的模塊系統,允許開發者將代碼分割到不同的模塊和文件中,同時控制代碼的可見性和組織結構。本章將深入探討Rust的模塊系統,包括包、crate、模塊的概念,路徑與作用域的使用,use關鍵字與重導出的技巧,以及文件組織與模塊拆分的最佳實踐。

8.1 包、crate和模塊

Rust代碼組織的基本概念

Rust的模塊系統由幾個關鍵概念組成:包(packages)、crate、模塊(modules)。理解這些概念的關係對於構建可維護的Rust項目至關重要。

包(Packages)

包是Rust中最頂層的組織單位。一個包包含一個或多個crate,以及一個描述包信息和依賴關係的Cargo.toml文件。

創建新包的命令:

cargo new my_project
cd my_project

這會創建一個包含以下結構的新包:

my_project/
├── Cargo.toml
└── src/
    └── main.rs
Crate

Crate是Rust的編譯單元,可以是二進制crate或庫crate:

  • 二進制crate:編譯為可執行文件,必須包含main函數作為程序入口
  • 庫crate:不包含main函數,提供功能供其他crate使用

一個包可以包含:

  • 最多一個庫crate(src/lib.rs
  • 零個或多個二進制crate(src/main.rssrc/bin/目錄下的文件)
  • 零個或多個示例、測試和基準測試crate
模塊(Modules)

模塊是Rust中代碼組織的核心機制,允許你將相關的函數、結構體、枚舉等分組在一起,並控制它們的可見性。

創建和使用模塊

基本模塊定義

模塊使用mod關鍵字定義:

// 定義一個名為network的模塊
mod network {
    fn connect() {
        println!("Connecting to network...");
    }
    
    mod server {
        fn start() {
            println!("Server starting...");
        }
    }
}

fn main() {
    // 無法直接訪問,因為模塊內的函數默認是私有的
    // network::connect(); // 這行會編譯錯誤
}
模塊的可見性

默認情況下,模塊內的所有項(函數、結構體、枚舉等)都是私有的。使用pub關鍵字使其變為公有:

mod network {
    pub fn connect() {
        println!("Connecting to network...");
    }
    
    pub mod server {
        pub fn start() {
            println!("Server starting...");
        }
        
        // 私有函數,只能在server模塊內部訪問
        fn internal_operation() {
            println!("Internal server operation");
        }
    }
}

fn main() {
    // 現在可以訪問了
    network::connect();
    network::server::start();
}

模塊的層次結構

模塊可以嵌套,形成層次結構:

mod communications {
    pub mod network {
        pub mod tcp {
            pub fn connect(host: &str, port: u16) {
                println!("TCP connecting to {}:{}", host, port);
            }
            
            pub fn disconnect() {
                println!("TCP disconnecting");
            }
        }
        
        pub mod udp {
            pub fn send_datagram(data: &[u8]) {
                println!("UDP sending {} bytes", data.len());
            }
        }
    }
    
    pub mod serial {
        pub fn open(device: &str) {
            println!("Opening serial device: {}", device);
        }
    }
}

fn main() {
    communications::network::tcp::connect("localhost", 8080);
    communications::serial::open("/dev/ttyUSB0");
}

模塊作為接口設計工具

模塊不僅是組織工具,還是設計API邊界的重要手段:

pub mod api {
    // 公有接口
    pub struct DatabaseConnection {
        // 私有字段,外部無法直接訪問
        connection_string: String,
        timeout: u32,
    }
    
    impl DatabaseConnection {
        // 公有構造函數
        pub fn new(connection_string: &str) -> Self {
            DatabaseConnection {
                connection_string: connection_string.to_string(),
                timeout: 30, // 默認超時
            }
        }
        
        // 公有方法
        pub fn connect(&self) -> Result<(), String> {
            self.internal_connect().map_err(|e| e.to_string())
        }
        
        pub fn set_timeout(&mut self, timeout: u32) {
            self.timeout = timeout;
        }
        
        // 私有方法,內部實現細節
        fn internal_connect(&self) -> Result<(), ConnectionError> {
            // 實際的連接邏輯
            println!("Connecting to: {}", self.connection_string);
            Ok(())
        }
    }
    
    // 私有錯誤類型,不暴露給外部
    #[derive(Debug)]
    struct ConnectionError {
        details: String,
    }
    
    impl ConnectionError {
        fn new(msg: &str) -> Self {
            ConnectionError { details: msg.to_string() }
        }
    }
    
    impl std::fmt::Display for ConnectionError {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
            write!(f, "Connection error: {}", self.details)
        }
    }
}

fn main() {
    use api::DatabaseConnection;
    
    let mut db = DatabaseConnection::new("postgres://localhost/mydb");
    db.set_timeout(60);
    
    match db.connect() {
        Ok(()) => println!("Connected successfully"),
        Err(e) => println!("Connection failed: {}", e),
    }
    
    // 無法訪問私有字段
    // println!("{}", db.connection_string); // 編譯錯誤
    
    // 無法訪問私有類型
    // let error = ConnectionError::new("test"); // 編譯錯誤
}

實戰:配置管理系統

讓我們構建一個配置管理系統來演示模塊的使用:

// 配置管理模塊
pub mod config {
    use std::collections::HashMap;
    use std::fs;
    use std::path::Path;
    
    // 配置錯誤類型
    #[derive(Debug)]
    pub enum ConfigError {
        FileNotFound(String),
        ParseError(String),
        InvalidValue(String),
    }
    
    impl std::fmt::Display for ConfigError {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
            match self {
                ConfigError::FileNotFound(path) => write!(f, "Config file not found: {}", path),
                ConfigError::ParseError(details) => write!(f, "Parse error: {}", details),
                ConfigError::InvalidValue(details) => write!(f, "Invalid value: {}", details),
            }
        }
    }
    
    impl std::error::Error for ConfigError {}
    
    // 主配置結構
    pub struct Config {
        values: HashMap<String, String>,
        source: ConfigSource,
    }
    
    // 配置來源枚舉
    enum ConfigSource {
        File(String),
        Memory,
        Environment,
    }
    
    impl Config {
        // 從文件加載配置
        pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ConfigError> {
            let path_str = path.as_ref().to_string_lossy().to_string();
            let content = fs::read_to_string(&path)
                .map_err(|_| ConfigError::FileNotFound(path_str.clone()))?;
            
            let values = Self::parse_config(&content)?;
            
            Ok(Config {
                values,
                source: ConfigSource::File(path_str),
            })
        }
        
        // 從內存數據創建配置
        pub fn from_memory(data: &[(&str, &str)]) -> Self {
            let values = data.iter()
                .map(|(k, v)| (k.to_string(), v.to_string()))
                .collect();
            
            Config {
                values,
                source: ConfigSource::Memory,
            }
        }
        
        // 獲取字符串值
        pub fn get_str(&self, key: &str) -> Option<&str> {
            self.values.get(key).map(|s| s.as_str())
        }
        
        // 獲取整數
        pub fn get_int(&self, key: &str) -> Result<Option<i64>, ConfigError> {
            if let Some(value) = self.get_str(key) {
                value.parse()
                    .map(Some)
                    .map_err(|_| ConfigError::InvalidValue(
                        format!("Expected integer for key '{}', got '{}'", key, value)
                    ))
            } else {
                Ok(None)
            }
        }
        
        // 獲取布爾值
        pub fn get_bool(&self, key: &str) -> Result<Option<bool>, ConfigError> {
            if let Some(value) = self.get_str(key) {
                match value.to_lowercase().as_str() {
                    "true" | "1" | "yes" | "on" => Ok(Some(true)),
                    "false" | "0" | "no" | "off" => Ok(Some(false)),
                    _ => Err(ConfigError::InvalidValue(
                        format!("Expected boolean for key '{}', got '{}'", key, value)
                    )),
                }
            } else {
                Ok(None)
            }
        }
        
        // 設置值
        pub fn set(&mut self, key: &str, value: &str) {
            self.values.insert(key.to_string(), value.to_string());
        }
        
        // 解析配置內容(簡單實現)
        fn parse_config(content: &str) -> Result<HashMap<String, String>, ConfigError> {
            let mut values = HashMap::new();
            
            for line in content.lines() {
                let line = line.trim();
                
                // 跳過空行和註釋
                if line.is_empty() || line.starts_with('#') {
                    continue;
                }
                
                // 簡單的鍵值解析
                if let Some(separator_pos) = line.find('=') {
                    let key = line[..separator_pos].trim();
                    let value = line[separator_pos + 1..].trim();
                    
                    if key.is_empty() {
                        return Err(ConfigError::ParseError(
                            "Empty key in config".to_string()
                        ));
                    }
                    
                    values.insert(key.to_string(), value.to_string());
                } else {
                    return Err(ConfigError::ParseError(
                        format!("Invalid line in config: '{}'", line)
                    ));
                }
            }
            
            Ok(values)
        }
    }
    
    // 配置構建器,用於構建複雜配置
    pub struct ConfigBuilder {
        values: HashMap<String, String>,
    }
    
    impl ConfigBuilder {
        pub fn new() -> Self {
            ConfigBuilder {
                values: HashMap::new(),
            }
        }
        
        pub fn with_value(mut self, key: &str, value: &str) -> Self {
            self.values.insert(key.to_string(), value.to_string());
            self
        }
        
        pub fn build(self) -> Config {
            Config {
                values: self.values,
                source: ConfigSource::Memory,
            }
        }
    }
}

// 使用配置系統
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use config::{Config, ConfigBuilder};
    
    // 從內存創建配置
    let config = ConfigBuilder::new()
        .with_value("server.host", "localhost")
        .with_value("server.port", "8080")
        .with_value("debug.enabled", "true")
        .with_value("database.connections", "10")
        .build();
    
    // 讀取配置值
    if let Some(host) = config.get_str("server.host") {
        println!("Server host: {}", host);
    }
    
    if let Ok(Some(port)) = config.get_int("server.port") {
        println!("Server port: {}", port);
    }
    
    if let Ok(Some(debug)) = config.get_bool("debug.enabled") {
        println!("Debug mode: {}", debug);
    }
    
    // 嘗試從文件加載(如果文件存在)
    match Config::from_file("config.txt") {
        Ok(file_config) => {
            println!("Loaded config from file");
            if let Some(value) = file_config.get_str("file.setting") {
                println!("File setting: {}", value);
            }
        }
        Err(e) => {
            println!("Could not load config file: {}", e);
        }
    }
    
    Ok(())
}

8.2 路徑與作用域

路徑的概念

在Rust中,路徑用於在模塊樹中定位項。路徑有兩種形式:

  • 絕對路徑:從crate根開始,以crate名或字面值crate開頭
  • 相對路徑:從當前模塊開始,使用selfsuper或當前模塊的標識符

路徑示例

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {
            println!("Adding to waitlist");
        }
        
        fn seat_at_table() {
            println!("Seating at table");
        }
    }
    
    mod serving {
        fn take_order() {
            println!("Taking order");
            
            // 相對路徑訪問同級模塊
            super::hosting::add_to_waitlist();
        }
        
        fn serve_order() {
            println!("Serving order");
        }
        
        fn take_payment() {
            println!("Taking payment");
        }
    }
}

pub fn eat_at_restaurant() {
    // 絕對路徑
    crate::front_of_house::hosting::add_to_waitlist();
    
    // 相對路徑
    front_of_house::hosting::add_to_waitlist();
}

fn deliver_order() {
    // 無法訪問私有模塊
    // front_of_house::serving::serve_order(); // 編譯錯誤
}

mod back_of_house {
    pub struct Breakfast {
        pub toast: String,
        seasonal_fruit: String, // 私有字段
    }
    
    impl Breakfast {
        pub fn summer(toast: &str) -> Self {
            Breakfast {
                toast: toast.to_string(),
                seasonal_fruit: String::from("peaches"),
            }
        }
        
        // 提供訪問私有字段的方法
        pub fn get_fruit(&self) -> &str {
            &self.seasonal_fruit
        }
    }
    
    pub enum Appetizer {
        Soup,
        Salad,
    }
    
    fn fix_incorrect_order() {
        cook_order();
        
        // 使用super訪問父模塊
        super::deliver_order();
    }
    
    fn cook_order() {
        println!("Cooking order");
    }
}

fn order_breakfast() {
    // 創建Breakfast實例
    let mut meal = back_of_house::Breakfast::summer("Rye");
    
    // 可以修改公有字段
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);
    
    // 無法直接訪問私有字段
    // meal.seasonal_fruit = String::from("blueberries"); // 編譯錯誤
    
    // 但可以通過公有方法訪問
    println!("With seasonal fruit: {}", meal.get_fruit());
    
    // 枚舉的所有變體都是公有的
    let order1 = back_of_house::Appetizer::Soup;
    let order2 = back_of_house::Appetizer::Salad;
}

使用super進行相對路徑訪問

super關鍵字允許我們引用父模塊,類似於文件系統中的..

mod sound {
    pub mod instrument {
        pub fn clarinet() {
            println!("Playing clarinet");
            
            // 使用super訪問父模塊
            super::breathe_in();
        }
    }
    
    fn breathe_in() {
        println!("Breathing in");
    }
    
    mod voice {
        pub fn sing() {
            println!("Singing");
            
            // 訪問祖父模塊
            super::super::start_performance();
        }
    }
}

fn start_performance() {
    println!("Starting performance");
}

mod performance {
    pub fn start() {
        // 使用super訪問父模塊(crate根)
        super::sound::instrument::clarinet();
        // super::sound::voice::sing(); // 無法訪問,因為voice模塊是私有的
    }
}

fn main() {
    performance::start();
}

結構體字段的可見性

結構體字段的可見性需要單獨指定:

mod user_management {
    pub struct User {
        pub username: String,
        pub email: String,
        active: bool,        // 私有字段
        sign_in_count: u64,  // 私有字段
    }
    
    impl User {
        pub fn new(username: &str, email: &str) -> Self {
            User {
                username: username.to_string(),
                email: email.to_string(),
                active: true,
                sign_in_count: 1,
            }
        }
        
        pub fn deactivate(&mut self) {
            self.active = false;
        }
        
        pub fn is_active(&self) -> bool {
            self.active
        }
        
        pub fn increment_sign_in(&mut self) {
            self.sign_in_count += 1;
        }
        
        pub fn get_sign_in_count(&self) -> u64 {
            self.sign_in_count
        }
    }
}

fn main() {
    let mut user = user_management::User::new("alice", "alice@example.com");
    
    // 可以訪問公有字段
    println!("Username: {}", user.username);
    println!("Email: {}", user.email);
    
    // 無法直接訪問私有字段
    // println!("Active: {}", user.active); // 編譯錯誤
    // println!("Sign in count: {}", user.sign_in_count); // 編譯錯誤
    
    // 但可以通過公有方法訪問和修改
    println!("Active: {}", user.is_active());
    println!("Sign in count: {}", user.get_sign_in_count());
    
    user.increment_sign_in();
    user.deactivate();
    
    println!("After changes - Active: {}, Sign in count: {}", 
             user.is_active(), user.get_sign_in_count());
}

實戰:權限系統

讓我們構建一個權限系統來演示路徑和可見性的使用:

pub mod auth {
    use std::collections::HashSet;
    
    // 用户角色
    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
    pub enum Role {
        Guest,
        User,
        Moderator,
        Admin,
    }
    
    // 權限
    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
    pub enum Permission {
        ReadPosts,
        WritePosts,
        DeletePosts,
        ManageUsers,
        SystemConfig,
    }
    
    // 用户信息
    pub struct User {
        username: String,
        roles: HashSet<Role>,
        is_active: bool,
    }
    
    impl User {
        pub fn new(username: &str) -> Self {
            let mut roles = HashSet::new();
            roles.insert(Role::Guest);
            
            User {
                username: username.to_string(),
                roles,
                is_active: true,
            }
        }
        
        pub fn get_username(&self) -> &str {
            &self.username
        }
        
        pub fn add_role(&mut self, role: Role) {
            self.roles.insert(role);
        }
        
        pub fn remove_role(&mut self, role: &Role) {
            self.roles.remove(role);
        }
        
        pub fn has_role(&self, role: &Role) -> bool {
            self.roles.contains(role)
        }
        
        pub fn deactivate(&mut self) {
            self.is_active = false;
        }
        
        pub fn is_active(&self) -> bool {
            self.is_active
        }
    }
    
    // 權限檢查器
    pub struct PermissionChecker;
    
    impl PermissionChecker {
        pub fn can_user_perform(user: &User, permission: &Permission) -> bool {
            if !user.is_active() {
                return false;
            }
            
            match permission {
                Permission::ReadPosts => true, // 所有人都可以讀
                Permission::WritePosts => {
                    user.has_role(&Role::User) || 
                    user.has_role(&Role::Moderator) || 
                    user.has_role(&Role::Admin)
                }
                Permission::DeletePosts => {
                    user.has_role(&Role::Moderator) || 
                    user.has_role(&Role::Admin)
                }
                Permission::ManageUsers => {
                    user.has_role(&Role::Admin)
                }
                Permission::SystemConfig => {
                    user.has_role(&Role::Admin)
                }
            }
        }
        
        pub fn get_effective_permissions(user: &User) -> HashSet<Permission> {
            let mut permissions = HashSet::new();
            
            if !user.is_active() {
                return permissions;
            }
            
            // 基礎權限
            permissions.insert(Permission::ReadPosts);
            
            // 用户權限
            if user.has_role(&Role::User) || 
               user.has_role(&Role::Moderator) || 
               user.has_role(&Role::Admin) {
                permissions.insert(Permission::WritePosts);
            }
            
            // 版主權限
            if user.has_role(&Role::Moderator) || user.has_role(&Role::Admin) {
                permissions.insert(Permission::DeletePosts);
            }
            
            // 管理員權限
            if user.has_role(&Role::Admin) {
                permissions.insert(Permission::ManageUsers);
                permissions.insert(Permission::SystemConfig);
            }
            
            permissions
        }
    }
    
    // 用户管理器
    pub struct UserManager {
        users: Vec<User>,
    }
    
    impl UserManager {
        pub fn new() -> Self {
            UserManager { users: Vec::new() }
        }
        
        pub fn create_user(&mut self, username: &str) -> Result<(), String> {
            if username.is_empty() {
                return Err("Username cannot be empty".to_string());
            }
            
            if self.users.iter().any(|u| u.get_username() == username) {
                return Err(format!("User '{}' already exists", username));
            }
            
            let user = User::new(username);
            self.users.push(user);
            
            Ok(())
        }
        
        pub fn find_user(&self, username: &str) -> Option<&User> {
            self.users.iter().find(|u| u.get_username() == username)
        }
        
        pub fn find_user_mut(&mut self, username: &str) -> Option<&mut User> {
            self.users.iter_mut().find(|u| u.get_username() == username)
        }
        
        pub fn promote_to_user(&mut self, username: &str) -> Result<(), String> {
            if let Some(user) = self.find_user_mut(username) {
                user.add_role(Role::User);
                Ok(())
            } else {
                Err(format!("User '{}' not found", username))
            }
        }
        
        pub fn promote_to_moderator(&mut self, username: &str) -> Result<(), String> {
            if let Some(user) = self.find_user_mut(username) {
                user.add_role(Role::User);
                user.add_role(Role::Moderator);
                Ok(())
            } else {
                Err(format!("User '{}' not found", username))
            }
        }
        
        pub fn promote_to_admin(&mut self, username: &str) -> Result<(), String> {
            if let Some(user) = self.find_user_mut(username) {
                user.add_role(Role::User);
                user.add_role(Role::Moderator);
                user.add_role(Role::Admin);
                Ok(())
            } else {
                Err(format!("User '{}' not found", username))
            }
        }
    }
}

// 使用權限系統
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use auth::{UserManager, Role, Permission, PermissionChecker};
    
    let mut user_manager = UserManager::new();
    
    // 創建用户
    user_manager.create_user("alice")?;
    user_manager.create_user("bob")?;
    user_manager.create_user("charlie")?;
    
    // 設置用户角色
    user_manager.promote_to_user("alice")?;
    user_manager.promote_to_moderator("bob")?;
    user_manager.promote_to_admin("charlie")?;
    
    // 檢查權限
    if let Some(alice) = user_manager.find_user("alice") {
        println!("Alice can write posts: {}", 
                 PermissionChecker::can_user_perform(alice, &Permission::WritePosts));
        println!("Alice can delete posts: {}", 
                 PermissionChecker::can_user_perform(alice, &Permission::DeletePosts));
        
        let permissions = PermissionChecker::get_effective_permissions(alice);
        println!("Alice's permissions: {:?}", permissions);
    }
    
    if let Some(bob) = user_manager.find_user("bob") {
        println!("Bob can delete posts: {}", 
                 PermissionChecker::can_user_perform(bob, &Permission::DeletePosts));
        println!("Bob can manage users: {}", 
                 PermissionChecker::can_user_perform(bob, &Permission::ManageUsers));
    }
    
    if let Some(charlie) = user_manager.find_user("charlie") {
        println!("Charlie can manage users: {}", 
                 PermissionChecker::can_user_perform(charlie, &Permission::ManageUsers));
        
        let permissions = PermissionChecker::get_effective_permissions(charlie);
        println!("Charlie's permissions: {:?}", permissions);
    }
    
    Ok(())
}

8.3 use關鍵字與重導出

使用use引入路徑

use關鍵字用於將路徑引入作用域,這樣就不需要每次都寫完整路徑:

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {
            println!("Adding to waitlist");
        }
        
        pub fn seat_at_table() {
            println!("Seating at table");
        }
    }
}

// 使用use引入路徑
use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    // 現在可以直接使用hosting,而不需要完整路徑
    hosting::add_to_waitlist();
    hosting::seat_at_table();
    
    // 仍然可以使用完整路徑
    crate::front_of_house::hosting::add_to_waitlist();
}

使用use引入函數

可以直接引入函數到作用域中:

mod utilities {
    pub fn format_timestamp(timestamp: u64) -> String {
        format!("{}", timestamp)
    }
    
    pub fn validate_email(email: &str) -> bool {
        email.contains('@')
    }
}

// 引入特定函數
use crate::utilities::format_timestamp;

fn main() {
    // 直接使用函數名
    let timestamp = format_timestamp(1627833600);
    println!("Formatted timestamp: {}", timestamp);
    
    // 其他函數仍然需要完整路徑
    let is_valid = crate::utilities::validate_email("test@example.com");
    println!("Email valid: {}", is_valid);
}

使用use引入結構體和枚舉

對於結構體和枚舉,通常引入類型本身,而不是其字段或變體:

mod types {
    pub struct User {
        pub username: String,
        pub email: String,
    }
    
    pub enum Status {
        Active,
        Inactive,
        Suspended,
    }
    
    impl User {
        pub fn new(username: &str, email: &str) -> Self {
            User {
                username: username.to_string(),
                email: email.to_string(),
            }
        }
    }
}

// 引入結構體和枚舉
use crate::types::{User, Status};

fn main() {
    // 可以直接使用User和Status
    let user = User::new("alice", "alice@example.com");
    let status = Status::Active;
    
    match status {
        Status::Active => println!("User is active"),
        Status::Inactive => println!("User is inactive"),
        Status::Suspended => println!("User is suspended"),
    }
}

重導出(Re-exporting)

使用pub use可以重導出項,這在創建模塊的公共API時非常有用:

// 內部模塊結構
mod internal {
    pub mod database {
        pub mod connection {
            pub fn connect() {
                println!("Database connecting");
            }
            
            pub fn disconnect() {
                println!("Database disconnecting");
            }
        }
        
        pub mod query {
            pub fn execute(sql: &str) {
                println!("Executing: {}", sql);
            }
        }
    }
    
    pub mod network {
        pub mod http {
            pub fn get(url: &str) {
                println!("HTTP GET: {}", url);
            }
            
            pub fn post(url: &str, data: &str) {
                println!("HTTP POST: {} with data: {}", url, data);
            }
        }
    }
}

// 重導出,創建更簡潔的公共API
pub use internal::database::connection::{connect, disconnect};
pub use internal::database::query::execute as db_execute;
pub use internal::network::http::{get, post};

// 內部模塊保持私有
// mod internal; // 通常這個模塊會放在單獨的文件中

fn main() {
    // 使用重導出的簡潔API
    connect();
    db_execute("SELECT * FROM users");
    get("https://example.com");
    disconnect();
    
    // 仍然可以使用完整路徑(但不推薦,因為internal模塊是私有的)
    // internal::database::connection::connect(); // 編譯錯誤,internal是私有的
}

使用as關鍵字重命名

使用as關鍵字可以為引入的項指定新名稱:

mod graphics {
    pub mod shapes {
        pub struct Circle {
            pub radius: f64,
        }
        
        pub struct Rectangle {
            pub width: f64,
            pub height: f64,
        }
        
        pub fn draw_circle(circle: &Circle) {
            println!("Drawing circle with radius: {}", circle.radius);
        }
        
        pub fn draw_rectangle(rect: &Rectangle) {
            println!("Drawing rectangle {}x{}", rect.width, rect.height);
        }
    }
}

// 使用as重命名
use crate::graphics::shapes::Circle as RoundShape;
use crate::graphics::shapes::Rectangle as RectShape;
use crate::graphics::shapes::{draw_circle, draw_rectangle as draw_rect};

fn main() {
    let circle = RoundShape { radius: 5.0 };
    let rectangle = RectShape { width: 10.0, height: 8.0 };
    
    draw_circle(&circle);
    draw_rect(&rectangle);
}

嵌套路徑

對於從同一個模塊或crate引入多個項,可以使用嵌套路徑來簡化:

// 傳統方式
// use std::cmp::Ordering;
// use std::io;
// use std::io::Write;

// 使用嵌套路徑
use std::{cmp::Ordering, io, io::Write};

// 使用self
use std::io::{self, Read, Write};

fn process_data() -> Result<(), io::Error> {
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)?;
    
    match buffer.cmp(&String::from("expected")) {
        Ordering::Less => println!("Less than expected"),
        Ordering::Equal => println!("Equal to expected"),
        Ordering::Greater => println!("Greater than expected"),
    }
    
    Ok(())
}

通配符導入

使用通配符*可以導入模塊中的所有公有項,但通常不推薦在生產代碼中使用,因為它會使代碼不清晰:

mod math {
    pub const PI: f64 = 3.14159;
    pub fn square(x: f64) -> f64 { x * x }
    pub fn cube(x: f64) -> f64 { x * x * x }
}

// 通配符導入(不推薦在生產代碼中使用)
use crate::math::*;

fn calculate_circle_area(radius: f64) -> f64 {
    PI * square(radius)
}

// 更好的方式:只導入需要的項
// use crate::math::{PI, square};

實戰:日誌系統

讓我們構建一個日誌系統來演示use和重導出的使用:

// 日誌系統
pub mod logging {
    use std::fmt;
    use std::sync::{Mutex, OnceLock};
    
    // 日誌級別
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
    pub enum LogLevel {
        Error = 1,
        Warn = 2,
        Info = 3,
        Debug = 4,
        Trace = 5,
    }
    
    impl fmt::Display for LogLevel {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{:?}", self)
        }
    }
    
    // 日誌記錄
    pub struct LogRecord<'a> {
        pub level: LogLevel,
        pub target: &'a str,
        pub message: String,
        pub timestamp: std::time::SystemTime,
    }
    
    impl<'a> LogRecord<'a> {
        pub fn new(level: LogLevel, target: &'a str, message: String) -> Self {
            LogRecord {
                level,
                target,
                message,
                timestamp: std::time::SystemTime::now(),
            }
        }
    }
    
    // 日誌處理器trait
    pub trait LogHandler: Send + Sync {
        fn handle(&self, record: &LogRecord);
    }
    
    // 控制枱處理器
    pub struct ConsoleHandler;
    
    impl LogHandler for ConsoleHandler {
        fn handle(&self, record: &LogRecord) {
            let timestamp = record.timestamp
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs();
            
            println!("[{}] {} {}: {}",
                     timestamp,
                     record.level,
                     record.target,
                     record.message);
        }
    }
    
    // 文件處理器
    pub struct FileHandler {
        file_path: String,
    }
    
    impl FileHandler {
        pub fn new(file_path: &str) -> Self {
            FileHandler {
                file_path: file_path.to_string(),
            }
        }
    }
    
    impl LogHandler for FileHandler {
        fn handle(&self, record: &LogRecord) {
            // 簡化實現,實際中需要實際的文件寫入
            println!("[FILE: {}] {} {}: {}",
                     self.file_path,
                     record.level,
                     record.target,
                     record.message);
        }
    }
    
    // 日誌器
    pub struct Logger {
        level: LogLevel,
        handlers: Vec<Box<dyn LogHandler>>,
    }
    
    impl Logger {
        pub fn new(level: LogLevel) -> Self {
            Logger {
                level,
                handlers: Vec::new(),
            }
        }
        
        pub fn add_handler(&mut self, handler: Box<dyn LogHandler>) {
            self.handlers.push(handler);
        }
        
        pub fn log(&self, level: LogLevel, target: &str, message: &str) {
            if level <= self.level {
                let record = LogRecord::new(level, target, message.to_string());
                
                for handler in &self.handlers {
                    handler.handle(&record);
                }
            }
        }
        
        // 便捷方法
        pub fn error(&self, target: &str, message: &str) {
            self.log(LogLevel::Error, target, message);
        }
        
        pub fn warn(&self, target: &str, message: &str) {
            self.log(LogLevel::Warn, target, message);
        }
        
        pub fn info(&self, target: &str, message: &str) {
            self.log(LogLevel::Info, target, message);
        }
        
        pub fn debug(&self, target: &str, message: &str) {
            self.log(LogLevel::Debug, target, message);
        }
        
        pub fn trace(&self, target: &str, message: &str) {
            self.log(LogLevel::Trace, target, message);
        }
    }
    
    // 全局日誌器
    static GLOBAL_LOGGER: OnceLock<Mutex<Logger>> = OnceLock::new();
    
    pub fn init_global_logger(level: LogLevel) {
        let logger = Logger::new(level);
        GLOBAL_LOGGER.get_or_init(|| Mutex::new(logger));
    }
    
    pub fn get_global_logger() -> Option<&'static Mutex<Logger>> {
        GLOBAL_LOGGER.get()
    }
    
    // 全局日誌函數
    pub fn error(target: &str, message: &str) {
        if let Some(logger) = get_global_logger() {
            if let Ok(logger) = logger.lock() {
                logger.error(target, message);
            }
        }
    }
    
    pub fn warn(target: &str, message: &str) {
        if let Some(logger) = get_global_logger() {
            if let Ok(logger) = logger.lock() {
                logger.warn(target, message);
            }
        }
    }
    
    pub fn info(target: &str, message: &str) {
        if let Some(logger) = get_global_logger() {
            if let Ok(logger) = logger.lock() {
                logger.info(target, message);
            }
        }
    }
    
    // 重導出常用項
    pub use self::LogLevel::{Error, Warn, Info, Debug, Trace};
}

// 使用重導出來創建簡潔的公共API
pub use logging::{
    init_global_logger,
    error, warn, info,
    LogLevel, Logger, ConsoleHandler, FileHandler, LogHandler
};

// 使用日誌系統
fn main() {
    // 初始化全局日誌器
    init_global_logger(LogLevel::Info);
    
    // 配置日誌器(簡化示例)
    if let Some(logger_mutex) = logging::get_global_logger() {
        if let Ok(mut logger) = logger_mutex.lock() {
            let console_handler = Box::new(ConsoleHandler);
            let file_handler = Box::new(FileHandler::new("app.log"));
            
            logger.add_handler(console_handler);
            logger.add_handler(file_handler);
        }
    }
    
    // 使用全局日誌函數
    error("main", "This is an error message");
    warn("main", "This is a warning message");
    info("main", "This is an info message");
    
    // Debug和Trace消息不會被記錄,因為日誌級別是Info
    logging::debug("main", "This debug message won't be shown");
    logging::trace("main", "This trace message won't be shown");
    
    // 使用直接導入的函數(通過重導出)
    use crate::{error, warn, info};
    
    error("network", "Network connection failed");
    warn("database", "Database query took too long");
    info("application", "Application started successfully");
}

8.4 文件組織與模塊拆分

將模塊拆分為文件

當項目增長時,將代碼拆分到不同文件中非常重要。Rust的模塊系統與文件系統緊密集成。

基本文件拆分

假設我們有以下的模塊結構:

src/
├── main.rs
└── lib.rs

我們可以將模塊拆分到不同的文件中:

src/main.rs:

// 聲明外部crate,如果項目是一個二進制crate
fn main() {
    println!("Hello, world!");
    my_library::public_function();
}

// 對於庫crate,通常在src/lib.rs中定義模塊

src/lib.rs:

// 聲明模塊,Rust會在同名文件中查找模塊代碼
pub mod network;
pub mod database;
pub mod utils;

// 重導出以創建乾淨的公共API
pub use network::connect;
pub use database::query;

src/network.rs:

pub fn connect() {
    println!("Network connecting");
}

pub mod tcp {
    pub fn connect(host: &str, port: u16) {
        println!("TCP connecting to {}:{}", host, port);
    }
}

pub mod udp {
    pub fn send(data: &[u8]) {
        println!("UDP sending {} bytes", data.len());
    }
}

src/database.rs:

pub fn query(sql: &str) -> Result<String, String> {
    Ok(format!("Result for: {}", sql))
}

pub mod connection {
    pub struct Connection {
        url: String,
    }
    
    impl Connection {
        pub fn new(url: &str) -> Self {
            Connection { url: url.to_string() }
        }
        
        pub fn execute(&self, sql: &str) -> Result<String, String> {
            Ok(format!("Executed '{}' on {}", sql, self.url))
        }
    }
}

src/utils.rs:

pub fn format_timestamp(timestamp: u64) -> String {
    format!("{}", timestamp)
}

pub fn validate_email(email: &str) -> bool {
    email.contains('@') && email.contains('.')
}

子目錄中的模塊

對於更復雜的模塊結構,可以使用子目錄:

src/lib.rs:

pub mod api;
pub mod models;
pub mod utils;

src/api/mod.rs: (模塊的主文件)

pub mod v1;
pub mod v2;

pub fn version() -> &'static str {
    "API"
}

src/api/v1/mod.rs:

pub mod users;
pub mod posts;

pub fn info() -> &'static str {
    "API v1"
}

src/api/v1/users.rs:

pub fn get_users() -> Vec<String> {
    vec!["Alice".to_string(), "Bob".to_string()]
}

pub fn create_user(username: &str) -> Result<String, String> {
    if username.is_empty() {
        Err("Username cannot be empty".to_string())
    } else {
        Ok(format!("User {} created", username))
    }
}

src/api/v1/posts.rs:

pub struct Post {
    pub title: String,
    pub content: String,
}

impl Post {
    pub fn new(title: &str, content: &str) -> Self {
        Post {
            title: title.to_string(),
            content: content.to_string(),
        }
    }
}

pub fn get_posts() -> Vec<Post> {
    vec![
        Post::new("First Post", "Hello, world!"),
        Post::new("Second Post", "Another post"),
    ]
}

src/models/mod.rs:

pub mod user;
pub mod post;

// 重導出常用結構體
pub use user::User;
pub use post::Post;

src/models/user.rs:

#[derive(Debug)]
pub struct User {
    pub id: u64,
    pub username: String,
    pub email: String,
}

impl User {
    pub fn new(id: u64, username: &str, email: &str) -> Self {
        User {
            id,
            username: username.to_string(),
            email: email.to_string(),
        }
    }
}

src/models/post.rs:

use super::user::User;

#[derive(Debug)]
pub struct Post {
    pub id: u64,
    pub title: String,
    pub content: String,
    pub author: User,
}

impl Post {
    pub fn new(id: u64, title: &str, content: &str, author: User) -> Self {
        Post {
            id,
            title: title.to_string(),
            content: content.to_string(),
            author,
        }
    }
}

使用mod.rs文件(舊風格)

Rust也支持使用mod.rs文件的舊風格模塊組織:

src/
├── main.rs
└── api/
    ├── mod.rs      // api模塊的主文件
    ├── v1/
    │   ├── mod.rs  // v1模塊的主文件
    │   ├── users.rs
    │   └── posts.rs
    └── v2/
        ├── mod.rs
        └── products.rs

src/api/mod.rs:

pub mod v1;
pub mod v2;

src/api/v1/mod.rs:

pub mod users;
pub mod posts;

現代Rust項目通常使用與模塊同名的.rs文件而不是mod.rs,但兩種風格都支持。

實戰:完整的Web應用結構

讓我們看一個完整的Web應用模塊結構示例:

項目結構:

my_web_app/
├── Cargo.toml
└── src/
    ├── main.rs
    ├── lib.rs
    ├── config.rs
    ├── routes/
    │   ├── mod.rs
    │   ├── api.rs
    │   └── web.rs
    ├── models/
    │   ├── mod.rs
    │   ├── user.rs
    │   └── post.rs
    ├── handlers/
    │   ├── mod.rs
    │   ├── user_handler.rs
    │   └── post_handler.rs
    └── middleware/
        ├── mod.rs
        ├── auth.rs
        └── logging.rs

src/main.rs:

use my_web_app::start_server;

fn main() {
    println!("Starting web server...");
    
    if let Err(e) = start_server() {
        eprintln!("Server error: {}", e);
        std::process::exit(1);
    }
}

src/lib.rs:

pub mod config;
pub mod routes;
pub mod models;
pub mod handlers;
pub mod middleware;

use config::Config;
use routes::{api_routes, web_routes};

pub fn start_server() -> Result<(), Box<dyn std::error::Error>> {
    let config = Config::load()?;
    
    println!("Server configured with:");
    println!("  Host: {}", config.host);
    println!("  Port: {}", config.port);
    println!("  Database URL: {}", config.database_url);
    
    // 在實際實現中,這裏會啓動HTTP服務器
    println!("Server would start on {}:{}", config.host, config.port);
    
    // 註冊路由
    api_routes::register();
    web_routes::register();
    
    Ok(())
}

// 重導出常用類型
pub use models::{User, Post};
pub use config::Config;

src/config.rs:

use std::env;
use std::fs;

#[derive(Debug, Clone)]
pub struct Config {
    pub host: String,
    pub port: u16,
    pub database_url: String,
    pub debug: bool,
}

impl Config {
    pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
        // 從環境變量加載配置
        let host = env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
        let port = env::var("PORT")
            .unwrap_or_else(|_| "8080".to_string())
            .parse()
            .unwrap_or(8080);
        
        let database_url = env::var("DATABASE_URL")
            .unwrap_or_else(|_| "postgres://localhost/mydb".to_string());
        
        let debug = env::var("DEBUG")
            .map(|v| v == "1" || v.to_lowercase() == "true")
            .unwrap_or(false);
        
        // 嘗試從配置文件加載(簡化實現)
        let _config_file = fs::read_to_string("config.toml").ok();
        
        Ok(Config {
            host,
            port,
            database_url,
            debug,
        })
    }
}

src/routes/mod.rs:

pub mod api_routes;
pub mod web_routes;

pub fn initialize() {
    println!("Initializing routes...");
    api_routes::register();
    web_routes::register();
}

src/routes/api_routes.rs:

use crate::handlers::{user_handler, post_handler};

pub fn register() {
    println!("Registering API routes:");
    println!("  GET /api/users");
    println!("  POST /api/users");
    println!("  GET /api/posts");
    println!("  POST /api/posts");
    
    // 在實際實現中,這裏會註冊到web框架的路由器
}

pub struct ApiRouter;

impl ApiRouter {
    pub fn new() -> Self {
        ApiRouter
    }
    
    pub fn handle_request(&self, path: &str, method: &str) {
        match (method, path) {
            ("GET", "/api/users") => user_handler::get_users(),
            ("POST", "/api/users") => user_handler::create_user(),
            ("GET", "/api/posts") => post_handler::get_posts(),
            ("POST", "/api/posts") => post_handler::create_post(),
            _ => println!("API route not found: {} {}", method, path),
        }
    }
}

src/routes/web_routes.rs:

pub fn register() {
    println!("Registering web routes:");
    println!("  GET /");
    println!("  GET /about");
    println!("  GET /contact");
}

pub struct WebRouter;

impl WebRouter {
    pub fn new() -> Self {
        WebRouter
    }
    
    pub fn handle_request(&self, path: &str) {
        match path {
            "/" => println!("Serving homepage"),
            "/about" => println!("Serving about page"),
            "/contact" => println!("Serving contact page"),
            _ => println!("Web route not found: {}", path),
        }
    }
}

src/models/mod.rs:

pub mod user;
pub mod post;

pub use user::User;
pub use post::Post;

src/models/user.rs:

#[derive(Debug, Clone)]
pub struct User {
    pub id: u64,
    pub username: String,
    pub email: String,
    pub active: bool,
}

impl User {
    pub fn new(id: u64, username: &str, email: &str) -> Self {
        User {
            id,
            username: username.to_string(),
            email: email.to_string(),
            active: true,
        }
    }
    
    pub fn deactivate(&mut self) {
        self.active = false;
    }
}

// 用户存儲(簡化實現)
pub struct UserStore {
    users: Vec<User>,
    next_id: u64,
}

impl UserStore {
    pub fn new() -> Self {
        UserStore {
            users: Vec::new(),
            next_id: 1,
        }
    }
    
    pub fn create_user(&mut self, username: &str, email: &str) -> Result<User, String> {
        if username.is_empty() {
            return Err("Username cannot be empty".to_string());
        }
        
        if self.users.iter().any(|u| u.username == username) {
            return Err(format!("Username '{}' already exists", username));
        }
        
        let user = User::new(self.next_id, username, email);
        self.next_id += 1;
        self.users.push(user.clone());
        
        Ok(user)
    }
    
    pub fn get_user(&self, id: u64) -> Option<&User> {
        self.users.iter().find(|u| u.id == id)
    }
    
    pub fn get_all_users(&self) -> &[User] {
        &self.users
    }
}

src/models/post.rs:

use super::user::User;

#[derive(Debug, Clone)]
pub struct Post {
    pub id: u64,
    pub title: String,
    pub content: String,
    pub author_id: u64,
    pub published: bool,
}

impl Post {
    pub fn new(id: u64, title: &str, content: &str, author_id: u64) -> Self {
        Post {
            id,
            title: title.to_string(),
            content: content.to_string(),
            author_id,
            published: false,
        }
    }
    
    pub fn publish(&mut self) {
        self.published = true;
    }
}

pub struct PostStore {
    posts: Vec<Post>,
    next_id: u64,
}

impl PostStore {
    pub fn new() -> Self {
        PostStore {
            posts: Vec::new(),
            next_id: 1,
        }
    }
    
    pub fn create_post(&mut self, title: &str, content: &str, author_id: u64) -> Post {
        let post = Post::new(self.next_id, title, content, author_id);
        self.next_id += 1;
        self.posts.push(post.clone());
        post
    }
    
    pub fn get_post(&self, id: u64) -> Option<&Post> {
        self.posts.iter().find(|p| p.id == id)
    }
    
    pub fn get_posts_by_author(&self, author_id: u64) -> Vec<&Post> {
        self.posts.iter()
            .filter(|p| p.author_id == author_id)
            .collect()
    }
}

src/handlers/mod.rs:

pub mod user_handler;
pub mod post_handler;

src/handlers/user_handler.rs:

use crate::models::user::{UserStore, User};

// 全局用户存儲(在實際應用中,這應該通過依賴注入)
static USER_STORE: std::sync::Mutex<UserStore> = std::sync::Mutex::new(UserStore::new());

pub fn get_users() {
    println!("Handling GET /api/users");
    
    let store = USER_STORE.lock().unwrap();
    let users = store.get_all_users();
    
    println!("Returning {} users", users.len());
    for user in users {
        println!("  User: {} ({})", user.username, user.email);
    }
}

pub fn create_user() {
    println!("Handling POST /api/users");
    
    let mut store = USER_STORE.lock().unwrap();
    
    // 在實際實現中,這裏會解析請求體
    match store.create_user("new_user", "new@example.com") {
        Ok(user) => println!("Created user: {} ({})", user.username, user.email),
        Err(e) => println!("Failed to create user: {}", e),
    }
}

pub fn get_user(user_id: u64) {
    println!("Handling GET /api/users/{}", user_id);
    
    let store = USER_STORE.lock().unwrap();
    
    if let Some(user) = store.get_user(user_id) {
        println!("Found user: {} ({})", user.username, user.email);
    } else {
        println!("User not found: {}", user_id);
    }
}

src/handlers/post_handler.rs:

use crate::models::post::PostStore;

// 全局文章存儲
static POST_STORE: std::sync::Mutex<PostStore> = std::sync::Mutex::new(PostStore::new());

pub fn get_posts() {
    println!("Handling GET /api/posts");
    
    let store = POST_STORE.lock().unwrap();
    let author_posts = store.get_posts_by_author(1); // 假設作者ID為1
    
    println!("Returning {} posts for author 1", author_posts.len());
    for post in author_posts {
        println!("  Post: {} (published: {})", post.title, post.published);
    }
}

pub fn create_post() {
    println!("Handling POST /api/posts");
    
    let mut store = POST_STORE.lock().unwrap();
    
    // 在實際實現中,這裏會解析請求體
    let post = store.create_post("New Post", "This is the content", 1);
    println!("Created post: {} (author: {})", post.title, post.author_id);
}

src/middleware/mod.rs:

pub mod auth;
pub mod logging;

src/middleware/auth.rs:

pub struct AuthMiddleware;

impl AuthMiddleware {
    pub fn new() -> Self {
        AuthMiddleware
    }
    
    pub fn authenticate(&self, token: &str) -> Result<u64, String> {
        if token.is_empty() {
            return Err("No authentication token provided".to_string());
        }
        
        // 簡化認證邏輯
        if token == "valid_token" {
            Ok(1) // 返回用户ID
        } else {
            Err("Invalid authentication token".to_string())
        }
    }
    
    pub fn authorize(&self, user_id: u64, resource: &str) -> bool {
        // 簡化授權邏輯
        user_id == 1 || resource == "public"
    }
}

src/middleware/logging.rs:

pub struct LoggingMiddleware;

impl LoggingMiddleware {
    pub fn new() -> Self {
        LoggingMiddleware
    }
    
    pub fn log_request(&self, method: &str, path: &str) {
        println!("[REQUEST] {} {}", method, path);
    }
    
    pub fn log_response(&self, status: u16, duration: std::time::Duration) {
        println!("[RESPONSE] Status: {}, Duration: {:?}", status, duration);
    }
}

測試模塊組織

良好的模塊組織也便於測試:

src/lib.rs (添加測試模塊):

// ... 其他代碼 ...

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_config_loading() {
        // 測試配置加載
    }
    
    // 更多測試...
}

src/models/user.rs (添加測試):

// ... User和UserStore實現 ...

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_user_creation() {
        let user = User::new(1, "testuser", "test@example.com");
        assert_eq!(user.username, "testuser");
        assert_eq!(user.email, "test@example.com");
        assert!(user.active);
    }
    
    #[test]
    fn test_user_store() {
        let mut store = UserStore::new();
        
        let user = store.create_user("alice", "alice@example.com").unwrap();
        assert_eq!(user.username, "alice");
        assert_eq!(user.id, 1);
        
        let found_user = store.get_user(1).unwrap();
        assert_eq!(found_user.username, "alice");
    }
}

最佳實踐總結

模塊設計最佳實踐

  1. 按功能分組:將相關的功能組織在同一個模塊中
  2. 控制可見性:使用pub關鍵字謹慎地暴露API,保持內部實現私有
  3. 使用重導出:通過pub use創建清晰的公共API
  4. 分層組織:使用模塊層次結構來反映代碼的邏輯結構

文件組織最佳實踐

  1. 一個文件一個模塊:對於中等大小的模塊,使用單獨的文件
  2. 使用目錄組織複雜模塊:對於包含子模塊的複雜模塊,使用目錄和mod.rs文件
  3. 保持一致的命名:模塊文件名應該與模塊名一致
  4. 避免過深的嵌套:模塊層次不宜過深,通常3-4層足夠

use關鍵字最佳實踐

  1. 在合適的作用域使用use:在函數內部或模塊頂部使用use
  2. 避免通配符導入:在生產代碼中避免使用*通配符
  3. 使用as解決命名衝突:當引入的項有命名衝突時,使用as重命名
  4. 分組導入:從同一個模塊導入多個項時,使用嵌套路徑

測試組織最佳實踐

  1. 與源代碼一起測試:在每個模塊中包含測試子模塊
  2. 使用cfg(test):使用#[cfg(test)]確保測試代碼只在測試時編譯
  3. 測試私有函數:在模塊內部測試私有函數
  4. 集成測試:在tests/目錄中編寫集成測試

通過遵循這些最佳實踐,你可以創建出結構清晰、易於維護的Rust項目。良好的模塊組織不僅使代碼更易於理解,還促進了代碼的重用和測試。

在下一章中,我們將探討Rust中的通用集合類型,包括Vector、String和HashMap,這些是構建複雜應用程序的基礎數據結構。