Rust: The Rust Module System and Cargo

Last updated: 2026-08-26

The module system is Rust's "code addressing scheme"—much like a building's street address, it allows you to pinpoint the location of every piece of code and control which parts of the code can be accessed from outside.

If a large project were a city, then modules (mods) would be neighborhoods, files would be buildings, and functions would be rooms. Cargo is the city administration—responsible for building roads, performing maintenance, and ensuring quality. Without a module system, the code would be a jumble of "urban villages."


1. What You'll Learn



2. The Story Behind the Apartment Numbering System

(1) Suffering: A City Without House Numbers

Tom moved into a newly built apartment building and discovered that it didn't have a house numbering system.

"It would be great if there were a standardized house numbering system: building-unit-apartment..."

(2) Approaches to the Rust Module System

TEXT 📖 Display only
Apartment(Crate)           → A building
  Building Name(crate name)   → Building Number
  Unit(Module)         → Apartment Building Entrance
    Room Number(Function)   → Specific Rooms
RUST
// File Structure Correspondence:
// src/
//   main.rs              → Apartment Lobby(Entrance)
//   building/
//     mod.rs             → Building Information
//     unit_1/
//       mod.rs           → 1 Unit
//       room_501.rs      → 501 Room
//       room_502.rs      → 502 Room

// In Rust, through mod and pub, precisely control who can access what
mod building {
    pub mod unit_1 {
        pub fn room_501() -> &'static str {
            "501 Room: Tom Home"
        }

        fn room_502() -> &'static str {
            "502 Room: Private Space"  // Default: Private, not visible externally
        }
    }
}

fn main() {
    // Access via the full path
    println!("{}", building::unit_1::room_501());
    // println!("{}", building::unit_1::room_502());  // ❌ Private Functions,Compilation Error
}

Rust's module system is like an apartment building's address system: crate represents the entire building, mod represents the unit, and fn represents the apartment. pub controls which apartments have doors opening to the outside; apartments without pub are private—outsiders cannot enter them freely.



3. Core Concepts

(1) Module System and Paths

100%
graph TB
    A[Rust Modular System] --> B[mod Definition]
    A --> C[pub Visibility]
    A --> D[use Path Import]
    A --> E[Cargo Project Management]

    B --> B1["mod Module Name { ... }"]
    B --> B2["mod Module Name;  // From a file"]

    C --> C1["pub: Visible to the public"]
    C --> C2["pub(crate): crate only, visible inside"]
    C --> C3["pub(super): Visible only to the parent module"]
    C --> C4["No pub: Private"]

    D --> D1["use crate::a::b::c;"]
    D --> D2["use super::module;"]
    D --> D3["use self::module;"]

    E --> E1["Cargo.toml Dependency"]
    E --> E2["cargo build / test"]
    E --> E3["workspace Multiple Packages"]
    E --> E4["lib.rs vs main.rs"]

(2) Comparison of Visibility Rules

Visibility Keywords Who Can Access Analogy
Private None (default) Current module and submodules Only family members can enter the bedroom
Visible to Parent Module pub(super) Parent Module Neighbors upstairs and downstairs can drop by
Visible within the crate pub(crate) All modules in the current crate Residents can enter the community gate
Public pub All external crates Anyone can enter the mall

(3) Path Types

Path Type Prefix Example Description
Absolute Path crate:: crate::utils::helper::foo Starting from the crate root
Relative Path self:: self::helper::foo Starting from the current module
Relative Path super:: super::helper::foo Starting from the parent module
External Path Package Name serde::Serialize Starting from an external crate

(4) Quick Reference for Common Cargo Commands

Command Function Common Options
cargo new Create a New Project --lib (Library Project)
cargo build Compile Project --release (Optimized Compilation)
cargo run Compile and run --bin name (specify binary)
cargo check Quickly check for compilation errors Faster than a build; does not generate binaries
cargo test Run Test test_name (Specified Test)
cargo doc Generate Document --open (Opens browser automatically)
cargo clippy Code lint checks -W clippy::all
cargo fmt Code Formatting --check (Check only, do not modify)
cargo add Add Dependency --features xxx
cargo update Update the dependency lock file Update Cargo.lock
cargo publish Publish to crates.io Must log in first
cargo clean Clean up build artifacts Delete the target/ directory


4. Modules and Cargo Examples

▶ Example 1: Module Definitions and pub Visibility (Difficulty ⭐)

Output:

TEXT 📖 Display only
<dish>
Dishes: <menu_item.get_price()>, Price: <menu_item.name> yuan
Chef Information: <restaurant::prepare_in_kitchen("Kung Pao Chicken")>
Price: <menu_item.price>
RUST
// ============================================
// Module Nesting、pub Visibility、Path Access
// Demo: The restaurant's kitchen is not visible to customers, but visible to servers
// ============================================

// Defining the Restaurant Module
mod restaurant {
    // Public: Customers may enter the restaurant
    pub struct Menu {
        pub name: String,
        price: f64,  // Default: Private,Not visible externally
    }

    impl Menu {
        // Public Constructor
        pub fn new(name: &str, price: f64) -> Menu {
            Menu {
                name: name.to_string(),
                price,
            }
        }

        // Public Methods: Get Price
        pub fn get_price(&self) -> f64 {
            self.price
        }
    }

    // Public: Customers can order food
    pub fn order_food(item: &str) -> String {
        // Private: Kitchen operations are not visible to customers
        let prepared = prepare_in_kitchen(item);
        format!("Your {} Ready: {}", item, prepared)
    }

    // Private: Customers are not allowed in the kitchen.
    fn prepare_in_kitchen(item: &str) -> String {
        format!("[Kitchen] {} Cooking in progress...", item)
    }

    // Nested Modules: Inside the Kitchen
    mod kitchen {
        // Private Storage Area
        pub struct Storage {
            pub items: Vec<String>,
        }

        impl Storage {
            pub fn new() -> Storage {
                Storage {
                    items: vec![
                        "Vegetables".to_string(),
                        "Meat".to_string(),
                        "Seasonings".to_string(),
                    ],
                }
            }
        }
    }
}

fn main() {
    // Accessing Public Module Members
    let dish = restaurant::order_food("Kung Pao Chicken");
    println!("{}", dish);

    // Create a public struct
    let menu_item = restaurant::Menu::new("Kung Pao Chicken", 38.0);
    println!("Dishes: {}, Price: {:.1} yuan", menu_item.name, menu_item.get_price());

    // The following code cannot be compiled(Uncomment this line to try it):
    // println!("Chef Information: {}", restaurant::prepare_in_kitchen("Kung Pao Chicken"));  // ❌ Private Functions
    // println!("Price: {}", menu_item.price);  // ❌ Private Fields
    // let storage = restaurant::kitchen::Storage::new();  // ❌ kitchen The module is private.
}

Output:

TEXT 📖 Display only
Your Kung Pao Chicken Ready: [Kitchen] Kung Pao Chicken Cooking in progress...
Dishes: Kung Pao Chicken, Price: 38.0 yuan

Module visibility rules are like the physical layout of a restaurant: customers (external code) can only enter the dining room (pub module) and cannot enter the kitchen (private modules). The operations taking place in the kitchen (prepare_in_kitchen) are completely invisible to the outside world—this is encapsulation.


▶ Example 2: use paths and super/crate (Difficulty: ⭐⭐)

Output:

TEXT 📖 Display only
<company::engineering::frontend::full_info()>
<frontend::full_info()>
<backend::full_info()>
Number of employees in the Marketing Department: <marketing::member_count()>
Total Number of Employees: <marketing::total_employees()>
Department: <eng::team_name()>
RUST
// ============================================
// use Keyword Import Path、super and crate Relative Path
// Simulation: Company Organizational Structure - Department→Group→Employees
// ============================================

// Top-Level Module: Company
mod company {
    // Engineering Department
    pub mod engineering {
        pub fn team_name() -> &'static str {
            "Engineering Department"
        }

        // Front-End Team
        pub mod frontend {
            pub fn member_count() -> u32 {
                5
            }

            // Use super to access the parent module (engineering)
            pub fn full_info() -> String {
                format!("{} Front-End Team, {} people", super::team_name(), member_count())
            }
        }

        // Backend Team
        pub mod backend {
            pub fn member_count() -> u32 {
                8
            }

            // Usage super Access the Parent Module
            pub fn full_info() -> String {
                format!("{} Backend Team, {} people", super::team_name(), member_count())
            }
        }
    }

    // Marketing Department
    pub mod marketing {
        pub fn team_name() -> &'static str {
            "Marketing Department"
        }

        // Usage crate Path Access from the Root
        pub fn total_employees() -> u32 {
            // From crate root, access begins
            crate::company::engineering::frontend::member_count()
            + crate::company::engineering::backend::member_count()
            + self::member_count()
        }

        fn member_count() -> u32 {
            6
        }
    }
}

// Usage use Import Path——Simplify the call
use company::engineering::frontend;
use company::engineering::backend;
use company::marketing;

fn main() {
    // Method 1: Full path (Not recommended, too long to write)
    println!("{}", company::engineering::frontend::full_info());

    // Method 2: Call directly after use import (Recommended)
    println!("{}", frontend::full_info());
    println!("{}", backend::full_info());

    // Introduction marketing Module
    println!("Number of employees in the Marketing Department: {}", marketing::member_count());

    // Usage crate Path Access
    println!("Total Number of Employees: {}", marketing::total_employees());

    // Usage as Avoiding Alias Conflicts
    use company::engineering as eng;
    println!("Department: {}", eng::team_name());
}

Output:

TEXT 📖 Display only
Engineering Department Front-End Team, 5 people
Engineering Department Backend Team, 8 people
Number of employees in the Marketing Department: 6
Total Number of Employees: 19
Department: Engineering Department

use It's like creating a shortcut for a "house number" - so you don't have to type out the full address every time company::engineering::frontend::full_info(). super means "go up one level" (parent module), and crate means "return to the building entrance" (crate root). as Keywords can be used to alias paths, resolving conflicts caused by duplicate names.


▶ Example 3: Dependency Management and Project Structure in Cargo.toml (Difficulty: ⭐⭐)

Output:

TEXT 📖 Display only
Today's Date: <date_utils::format_today()>
Email Verification: <string_utils::validate_email("test@example.com")>
Prime Number Check: <math_utils::is_prime(17)>
=== Tool Library Demo ===
Today: <date_utils::format_today()>
Is it the weekend?: <date_utils::is_weekend("Saturday")>
Email Verification test@example.com: <string_utils::validate_email("test@example.com")>
Email Verification invalid: <string_utils::validate_email("invalid")>
Purification 'hello@world!': <string_utils::sanitize("hello@world!")>
Fibonacci #10: <math_utils::fibonacci(10)>
17 Is it a prime number?: <math_utils::is_prime(17)>
4 Is it a prime number?: <math_utils::is_prime(4)>
=== End of Presentation ===
Usage `cargo test` Run Unit Tests
RUST
// ============================================
// Simulation Cargo Project Structure + Dependency Management
// Demo:lib.rs and main.rs Division of Labor、Using External Dependencies
// ============================================

// Note: This example demonstrates the code in lib.rs
// Actual Cargo.toml See the note below for the contents of the document.

// ============================================
// Cargo.toml Content (Simulation):
// ============================================
// [package]
// name = "my-toolkit"
// version = "0.1.0"
// edition = "2021"
//
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
// chrono = "0.4"
// regex = "1.10"
//
// [dev-dependencies]
// rand = "0.8"
//
// [profile.release]
// opt-level = 3
// ============================================

// Tools Module: Date Handling
pub mod date_utils {
    pub fn format_today() -> String {
        // Used in actual projects chrono::Local::now()
        "2026-07-03".to_string()
    }

    pub fn is_weekend(day: &str) -> bool {
        day.ends_with("Saturday") || day.ends_with("Sunday")
    }
}

// Tools Module: String Processing
pub mod string_utils {
    /// Verify the email address format (Simulating Regular Expression Matching)
    pub fn validate_email(email: &str) -> bool {
        // Simplified Verification: Use regex crate in practice
        email.contains('@') && email.contains('.')
    }

    /// Remove non-alphanumeric characters (Simulation)
    pub fn sanitize(input: &str) -> String {
        input.chars()
            .filter(|c| c.is_alphanumeric() || *c == ' ')
            .collect()
    }
}

// Tools Module: Mathematical Calculations
pub mod math_utils {
    /// Calculate the nth term of the nth term of the Fibonacci sequence
    pub fn fibonacci(n: u32) -> u64 {
        match n {
            0 => 0,
            1 => 1,
            _ => fibonacci(n - 1) + fibonacci(n - 2),
        }
    }

    /// Determining Whether a Number Is Prime
    pub fn is_prime(n: u32) -> bool {
        if n < 2 {
            return false;
        }
        let limit = (n as f64).sqrt() as u32;
        for i in 2..=limit {
            if n % i == 0 {
                return false;
            }
        }
        true
    }
}

// Test Module (Using #[cfg(test)] Conditional Compilation)
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validate_email() {
        assert!(string_utils::validate_email("user@example.com"));
        assert!(!string_utils::validate_email("invalid"));
    }

    #[test]
    fn test_fibonacci() {
        assert_eq!(math_utils::fibonacci(0), 0);
        assert_eq!(math_utils::fibonacci(1), 1);
        assert_eq!(math_utils::fibonacci(10), 55);
    }

    #[test]
    fn test_is_prime() {
        assert!(math_utils::is_prime(17));
        assert!(!math_utils::is_prime(1));
        assert!(!math_utils::is_prime(4));
    }

    #[test]
    fn test_sanitize() {
        assert_eq!(string_utils::sanitize("hello@world!"), "hello world");
    }
}

// ============================================
// main.rs The code in (Simulation):
// ============================================
// use my_toolkit::{
//     date_utils,
//     string_utils,
//     math_utils,
// };
//
// fn main() {
//     println!("Today's Date: {}", date_utils::format_today());
//     println!("Email Verification: {}", string_utils::validate_email("test@example.com"));
//     println!("Prime Number Check: {}", math_utils::is_prime(17));
// }

fn main() {
    // Demonstration of Each Tool's Functions
    println!("=== Tool Library Demo ===");

    // Date Tools
    println!("Today: {}", date_utils::format_today());
    println!("Is it the weekend?: {}", date_utils::is_weekend("Saturday"));

    // String Tools
    println!("Email Verification test@example.com: {}", string_utils::validate_email("test@example.com"));
    println!("Email Verification invalid: {}", string_utils::validate_email("invalid"));
    println!("Purification 'hello@world!': {}", string_utils::sanitize("hello@world!"));

    // Mathematical Tools
    println!("Fibonacci #10: {}", math_utils::fibonacci(10));
    println!("17 Is it a prime number?: {}", math_utils::is_prime(17));
    println!("4 Is it a prime number?: {}", math_utils::is_prime(4));

    println!("=== End of Presentation ===");

    // Instructions for Running the Test (Use cargo test in actual projects)
    println!("Usage `cargo test` Run Unit Tests");
}

Output:

TEXT 📖 Display only
=== Tool Library Demo ===
Today: 2026-07-03
Is it the weekend?: true
Email Verification test@example.com: true
Email Verification invalid: false
Purification 'hello@world!': hello world
Fibonacci #10: 55
17 Is it a prime number?: true
4 Is it a prime number?: false
=== End of Presentation ===
Usage `cargo test` Run Unit Tests

Standard structure for real projects: lib.rs contains the library code (public API), main.rs contains the executable entry point (which uses the library). Cargo.toml manages dependencies, [dependencies] contains production dependencies, and [dev-dependencies] contains test/build tool dependencies. cargo test Automatically discovers and runs functions marked with #[test].


▶ Example 4: Common Cargo Commands and Workspaces (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
=== Task Manager (Simulation Workspace Project) ===

--- All Tasks ---
#<task.title> [<task.id>] <task.status> - <task.priority>

Done #<id1> after:
#<task.id> <task.title> - <status>

Urgent Task: #<task.title> <task.priority> (<task.id>)

=== End of Presentation ===
Project Structure: task-core (Library) + task-cli (CLI) + task-web (Web)
RUST
// ============================================
// Cargo Common Commands and workspace Multi-Package Management
// Simulation: One "Task Manager" workspace Project
// ============================================

// ============================================
// Top Floor Cargo.toml (workspace):
// ============================================
// [workspace]
// members = [
//     "task-core",       // Core Library
//     "task-cli",        // CLI Tools
//     "task-web",        // Web Interface
// ]
//
// [workspace.package]
// version = "1.0.0"
// edition = "2021"
// ============================================

// ============================================
// task-core/Cargo.toml:
// ============================================
// [package]
// name = "task-core"
// version.workspace = true
// edition.workspace = true
//
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// chrono = "0.4"
// ============================================

// Simulation task-core Library code
pub mod task_core {
    use std::collections::HashMap;

    /// Task Priority
    #[derive(Debug, Clone, PartialEq)]
    pub enum Priority {
        Low,
        Medium,
        High,
        Urgent,
    }

    /// Task Status
    #[derive(Debug, Clone, PartialEq)]
    pub enum Status {
        Todo,
        InProgress,
        Done,
        Cancelled,
    }

    /// Core Task Structure
    #[derive(Debug, Clone)]
    pub struct Task {
        pub id: u64,
        pub title: String,
        pub priority: Priority,
        pub status: Status,
        pub tags: Vec<String>,
    }

    impl Task {
        pub fn new(id: u64, title: &str, priority: Priority) -> Task {
            Task {
                id,
                title: title.to_string(),
                priority,
                status: Status::Todo,
                tags: Vec::new(),
            }
        }

        pub fn add_tag(&mut self, tag: &str) {
            self.tags.push(tag.to_string());
        }

        pub fn is_completed(&self) -> bool {
            self.status == Status::Done || self.status == Status::Cancelled
        }
    }

    /// Task Manager
    pub struct TaskManager {
        tasks: HashMap<u64, Task>,
        next_id: u64,
    }

    impl TaskManager {
        pub fn new() -> TaskManager {
            TaskManager {
                tasks: HashMap::new(),
                next_id: 1,
            }
        }

        pub fn create_task(&mut self, title: &str, priority: Priority) -> u64 {
            let id = self.next_id;
            self.next_id += 1;
            let task = Task::new(id, title, priority);
            self.tasks.insert(id, task);
            id
        }

        pub fn get_task(&self, id: u64) -> Option<&Task> {
            self.tasks.get(&id)
        }

        pub fn complete_task(&mut self, id: u64) -> bool {
            if let Some(task) = self.tasks.get_mut(&id) {
                task.status = Status::Done;
                true
            } else {
                false
            }
        }

        pub fn list_tasks(&self) -> Vec<&Task> {
            let mut tasks: Vec<&Task> = self.tasks.values().collect();
            tasks.sort_by_key(|t| t.id);
            tasks
        }
    }
}

// ============================================
// Cargo Command Reference (Demonstrated in the comments):
// ============================================
// Common Commands:
//   cargo new project_name      -- Create a New Project
//   cargo build                 -- Compilation (debug)
//   cargo build --release       -- Compilation (release optimization)
//   cargo run                   -- Compilation + Run
//   cargo check                 -- Quickly Check for Compilation Errors (No binary files generated)
//   cargo test                  -- Run Test
//   cargo test test_name        -- Run the specified test
//   cargo bench                 -- Run Performance Benchmarks
//   cargo doc --open            -- Generate the document and open it
//   cargo clippy                -- Code lint Inspection
//   cargo fmt                   -- Code Formatting
//   cargo add crate_name        -- Add Dependencies
//   cargo update                -- Update Dependencies
//   cargo publish               -- Post to crates.io
//   cargo clean                 -- Clean up compilation output
//
// Workspace Commands:
//   cargo build --workspace     -- Compilation workspace All packages in
//   cargo test -p task-core     -- Test only the specified package
//   cargo run -p task-cli       -- Run the specified package

fn main() {
    use task_core::{Priority, TaskManager};

    println!("=== Task Manager (Simulation Workspace Project) ===");

    let mut manager = TaskManager::new();

    // Create a Task
    let id1 = manager.create_task("Study Rust Smart Pointers", Priority::High);
    let id2 = manager.create_task("Complete the module system exercises", Priority::Medium);
    let id3 = manager.create_task("Restore the Production Environment Bug", Priority::Urgent);

    // List all tasks
    println!("\n--- All Tasks ---");
    for task in manager.list_tasks() {
        println!("#{} [{:?}] {} - {:?}", task.id, task.priority, task.title, task.status);
    }

    // Complete a task
    manager.complete_task(id1);
    println!("\nDone #{} after:", id1);
    for task in manager.list_tasks() {
        let status = if task.is_completed() { "Completed" } else { "In progress" };
        println!("#{} {} - {}", task.id, task.title, status);
    }

    // Get a Single Task
    if let Some(task) = manager.get_task(id3) {
        println!("\nUrgent Task: #{} {} ({:?})", task.id, task.title, task.priority);
    }

    println!("\n=== End of Presentation ===");
    println!("Project Structure: task-core (Library) + task-cli (CLI) + task-web (Web)");
    println!("Usage `cargo test -p task-core` Testing the Core Library");
    println!("Usage `cargo doc --open` Generate Document");
}

Output:

TEXT 📖 Display only
=== Task Manager (Simulation Workspace Project) ===

--- All Tasks ---
#1 [High] Study Rust Smart Pointers - Todo
#2 [Medium] Complete the module system exercises - Todo
#3 [Urgent] Restore the Production Environment Bug - Todo

Done #1 after:
#1 Study Rust Smart Pointers - Completed
#2 Complete the module system exercises - In progress
#3 Restore the Production Environment Bug - In progress

Urgent Task: #3 Restore the Production Environment Bug (Urgent)

=== End of Presentation ===
Project Structure: task-core (Library) + task-cli (CLI) + task-web (Web)
Usage `cargo test -p task-core` Testing the Core Library
Usage `cargo doc --open` Generate Document

Workspace is a powerful tool for managing multi-package projects: task-core provides the core types and logic (libraries), task-cli provides the command-line interface (executable), task-web provides the Web API (another executable), and cargo build --workspace compiles all packages at once. cargo test -p task-core tests only the core libraries.


▶ Example 5: Comprehensive Exercise—Modular Design Simulation (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
=== math_utils Module ===
2 + 3 = <add(2, 3)>
4 * 5 = <multiply(4, 5)>
10 / 3 = <safe_divide(10, 3)>
10 / 0 = <safe_divide(10, 0)>
PI = <constants::PI>, E = <constants::E>

=== string_utils Module ===
capitalize: '<capitalize("rust")>'
truncate: '<truncate("Hello, World!", 8)>'

=== user Module ===
<alice.summary()>
Age: <alice.age()>
RUST
// ============================================
// Comprehensive Example: Module Visibility and API Design
// Simulating a Multi-File Project Structure (Actual projects should be broken down into separate files.)
// ============================================

mod math_utils {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    pub fn multiply(a: i32, b: i32) -> i32 { a * b }
    fn internal_check(val: i32) -> bool { val >= 0 }

    pub fn safe_divide(a: i32, b: i32) -> Option<i32> {
        if b == 0 { return None; }
        if !internal_check(a) || !internal_check(b) { return None; }
        Some(a / b)
    }

    pub mod constants {
        pub const PI: f64 = 3.14159265358979;
        pub const E: f64 = 2.71828182845905;
        pub const MAX_I32: i32 = i32::MAX;
    }
}

mod string_utils {
    pub fn capitalize(s: &str) -> String {
        let mut chars = s.chars();
        match chars.next() {
            None => String::new(),
            Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
        }
    }

    pub fn truncate(s: &str, max_len: usize) -> String {
        if s.len() <= max_len { s.to_string() }
        else { format!("{}...", &s[..max_len.min(s.len())]) }
    }
}

mod user {
    pub struct User {
        pub name: String,
        age: u8,
        email: String,
    }

    impl User {
        pub fn new(name: &str, age: u8, email: &str) -> Self {
            User { name: name.to_string(), age, email: email.to_string() }
        }

        pub fn age(&self) -> u8 { self.age }

        pub fn summary(&self) -> String {
            format!("{} ({} years old, {})", self.name, self.age, self.email)
        }
    }
}

fn main() {
    use math_utils::{add, multiply, safe_divide, constants};
    use string_utils::{capitalize, truncate};
    use user::User;

    println!("=== math_utils Module ===");
    println!("2 + 3 = {}", add(2, 3));
    println!("4 * 5 = {}", multiply(4, 5));
    println!("10 / 3 = {:?}", safe_divide(10, 3));
    println!("10 / 0 = {:?}", safe_divide(10, 0));
    println!("PI = {:.5}, E = {:.5}", constants::PI, constants::E);

    println!("\n=== string_utils Module ===");
    println!("capitalize: '{}'", capitalize("rust"));
    println!("truncate: '{}'", truncate("Hello, World!", 8));

    println!("\n=== user Module ===");
    let alice = User::new("Alice", 30, "alice@example.com");
    println!("{}", alice.summary());
    println!("Age: {}", alice.age());
}

Output:

TEXT 📖 Display only
=== math_utils Module ===
2 + 3 = 5
4 * 5 = 20
10 / 3 = Some(3)
10 / 0 = None
PI = 3.14159, E = 2.71828

=== string_utils Module ===
capitalize: 'Rust'
truncate: 'Hello, ...'

=== user Module ===
Alice (30 years old, alice@example.com)
Age: 30

Three Principles of Modular Design: pub Expose only the necessary APIs (such as add and safe_divide), and keep internal details (such as internal_check) private; Submodules (such as constants) are exposed via pub mod; structure fields are individually annotated with visibility (private pub name / age + age() getter).


❓ FAQ

Q What is the difference between mod and fn? Why not organize them using files?
A mod is a module definition, and fn is a function definition.
Q What is the difference between pub(crate) and pub?
A pub(crate) is visible only to code within the same crate, while pub is visible to all external crates.
Q When should use super::xxx and use crate::xxx be used?
A super is used to access the parent module (relative path), and crate is used to access content starting from the crate root (absolute path).
Q What does the version number ^1.2.3 in Cargo.toml mean?
A ^ stands for "compatibility update"—a version that allows >=1.2.3 and <2.0.0.
Q Can lib.rs and main.rs coexist?
A Yes.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Create a program containing two modules, math and greeting. The math module has a public function add(a: i32, b: i32) -> i32, and the greeting module has a public function say_hello(name: &str) -> String. Call both of these functions in main.
  2. Difficulty ⭐⭐: Simulate a "library" module system. Create the library module, which includes the books submodule (book management) and the members submodule (member management). books contains the add_book and list_books functions, and members contains the add_member and list_members functions. Use pub(super) and pub(crate) to control visibility appropriately. The main module demonstrates how to add books and members.
  3. Difficulty ⭐⭐⭐: Explore the Cargo workspace project structure. Create a workspace project locally that includes core-lib (a library providing the add and subtract functions) and cli-app (an executable that performs calculations using core-lib and prints the results). Configure the workspace settings for Cargo.toml, compile it using cargo build --workspace, and run it using cargo run -p cli-app.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏