Rust: O Sistema de Módulos do Rust e o Cargo

Última atualização: 2026-08-26

O sistema de módulos é o “esquema de endereçamento de código” do Rust — assim como o endereço de um prédio, ele permite identificar com precisão a localização de cada trecho de código e controlar quais partes do código podem ser acessadas externamente.

Se um grande projeto fosse uma cidade, os módulos (mods) seriam os bairros, os arquivos seriam os prédios e as funções seriam os cômodos. O Cargo é a administração da cidade — responsável por construir estradas, realizar manutenção e garantir a qualidade. Sem um sistema de módulos, o código seria uma confusão de “aldeias urbanas”.


1. O que você vai aprender


2. A história por trás do sistema de numeração dos apartamentos

(1) Sofrimento: Uma cidade sem números nas casas

Tom se mudou para um prédio de apartamentos recém-construído e descobriu que ele não tinha um sistema de numeração das residências.

“Seria ótimo se houvesse um sistema padronizado de numeração de residências: prédio-unidade-apartamento...”

(2) Abordagens ao sistema de módulos do Rust

TEXT 📖 Somente leitura
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
}

O sistema de módulos do Rust é como o sistema de endereçamento de um prédio de apartamentos: crate representa o prédio inteiro, mod representa o bloco e fn representa o apartamento. pub controla quais apartamentos têm portas que se abrem para o exterior; os apartamentos sem pub são privados — pessoas de fora não podem entrar neles livremente.


3. Conceitos fundamentais

(1) Sistema de módulos e caminhos

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) Comparação das regras de visibilidade

Visibilidade Palavras-chave Quem pode acessar Analogia
Privado Nenhum (padrão) Módulo atual e submódulos Somente membros da família podem entrar no quarto
Visível para o módulo pai pub(super) Módulo pai Os vizinhos do andar de cima e de baixo podem dar uma passada por aqui
Visível dentro do crate pub(crate) Todos os módulos no crate atual Os moradores podem entrar pelo portão da comunidade
Público pub Todas as caixas externas Qualquer pessoa pode entrar no shopping

(3) Tipos de caminho

Tipo de caminho Prefixo Exemplo Descrição
Caminho absoluto crate:: crate::utils::helper::foo A partir da raiz do crate
Caminho relativo self:: self::helper::foo A partir do módulo atual
Caminho relativo super:: super::helper::foo A partir do módulo pai
Caminho externo Nome do pacote serde::Serialize A partir de um crate externo

(4) Referência rápida para comandos comuns de carga

Comando Função Opções comuns
cargo new Criar um novo projeto --lib (Projeto de biblioteca)
cargo build Compilar projeto --release (Compilação otimizada)
cargo run Compilar e executar --bin name (especificar binário)
cargo check Verifica rapidamente se há erros de compilação Mais rápido do que uma compilação; não gera binários
cargo test Executar teste test_name (Teste especificado)
cargo doc Gerar documento --open (Abre o navegador automaticamente)
cargo clippy Verificações de lint de código -W clippy::all
cargo fmt Formatação de código --check (Apenas verifique, não altere)
cargo add Adicionar dependência --features xxx
cargo update Atualizar o arquivo de bloqueio de dependências Atualizar o Cargo.lock
cargo publish Publicar no crates.io É preciso fazer login primeiro
cargo clean Limpar artefatos de compilação Excluir o diretório target/

4. Módulos e exemplos do Cargo

▶ Exemplo 1: Definições de módulos e visibilidade pub (Dificuldade ⭐)

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.
}

Resultado:

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

As regras de visibilidade dos módulos são como o layout físico de um restaurante: os clientes (código externo) só podem entrar na sala de jantar (módulo pub) e não podem entrar na cozinha (módulos privados). As operações que ocorrem na cozinha (prepare_in_kitchen) são completamente invisíveis para o mundo exterior — isso é encapsulamento.


▶ Exemplo 2: caminhos use e super/crate (Dificuldade: ⭐⭐)

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());
}

Resultado:

TEXT 📖 Somente leitura
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 É como criar um atalho para um “número de casa” — assim, você não precisa digitar o endereço completo todas as vezes company::engineering::frontend::full_info(). super significa “subir um nível” (módulo pai), e crate significa “voltar à entrada do prédio” (raiz da caixa). as Palavras-chave podem ser usadas para criar aliases de caminhos, resolvendo conflitos causados por nomes duplicados.


▶ Exemplo 3: Gerenciamento de dependências e estrutura do projeto no Cargo.toml (Dificuldade: ⭐⭐)

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");
}

Resultado:

TEXT 📖 Somente leitura
=== 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

Estrutura padrão para projetos reais: lib.rs contém o código da biblioteca (API pública), main.rs contém o ponto de entrada do executável (que utiliza a biblioteca). Cargo.toml gerencia as dependências, [dependencies] contém as dependências de produção e [dev-dependencies] contém as dependências de ferramentas de teste/compilação. cargo test detecta e executa automaticamente as funções marcadas com #[test].


▶ Exemplo 4: Comandos e áreas de trabalho comuns do Cargo (Dificuldade ⭐⭐⭐)

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");
}

Resultado:

TEXT 📖 Somente leitura
=== 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

O Workspace é uma ferramenta poderosa para gerenciar projetos com vários pacotes: task-core fornece os tipos e a lógica principais (bibliotecas), task-cli fornece a interface de linha de comando (executável), task-web fornece a API da Web (outro executável) e cargo build --workspace compila todos os pacotes de uma só vez. O cargo test -p task-core testa apenas as bibliotecas principais.


▶ Exemplo 5: Exercício abrangente — Simulação de projeto modular (Dificuldade ⭐⭐⭐)

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());
}

Resultado:

TEXT 📖 Somente leitura
=== 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

Três princípios do design modular: pub Expor apenas as APIs necessárias (como add e safe_divide) e manter os detalhes internos (como internal_check) privados; Os submódulos (como constants) são expostos por meio de pub mod; os campos da estrutura são anotados individualmente com visibilidade (privado pub name / age + getter age()).


❓ Perguntas Frequentes

P: Qual é a diferença entre mod e fn? Por que não organizá-los usando arquivos? R: mod é uma definição de módulo, e fn é uma definição de função. O Rust suporta duas abordagens: mod xxx { ... } inline ou arquivos mod xxx; (carregados a partir de xxx.rs ou xxx/mod.rs). A abordagem baseada em arquivos oferece maior clareza em projetos grandes, mas as regras de visibilidade de um módulo não são afetadas pela estrutura do arquivo — elas são controladas exclusivamente pela palavra-chave pub.

P: Qual é a diferença entre pub(crate) e pub? R: pub(crate) é visível apenas para o código dentro do mesmo crate, enquanto pub é visível para todos os crates externos. Se você estiver escrevendo uma biblioteca, as funções auxiliares internas devem usar pub(crate) em vez de pub, para que usuários externos não vejam APIs internas que não devem ser utilizadas.

P: Quando se deve usar use super::xxx e use crate::xxx? R: super é usado para acessar o módulo pai (caminho relativo), e crate é usado para acessar o conteúdo a partir da raiz do crate (caminho absoluto). Recomendamos o uso de crate (caminhos absolutos), pois os caminhos relativos são propensos a erros durante a refatoração. super é usado principalmente em submódulos para acessar rapidamente o conteúdo do módulo pai.

P: O que significa o número de versão ^1.2.3 no Cargo.toml? R: ^ significa “atualização de compatibilidade” — uma versão que permite >=1.2.3 e <2.0.0. Essa é a regra padrão de versionamento semântico (SemVer) do Cargo: ^1.2.3 permite atualizações compatíveis com versões anteriores dentro do intervalo 1.x.x. =1.2.3 fixa a versão exata, e >=1.2.3 permite qualquer versão superior.

P: lib.rs e main.rs podem coexistir? R: Sim. lib.rs define a API pública da biblioteca, main.rs funciona como ponto de entrada do executável — main.rs importa o código de lib.rs por meio de use crate_name::xxx. Esse é um padrão comum em projetos Rust: seu código é colocado em lib.rs para facilitar testes e reutilização, enquanto main.rs serve apenas como um ponto de entrada simples.


📖 Resumo


📝 Exercícios

  1. Dificuldade ⭐: Crie um programa contendo dois módulos, math e greeting. O módulo math possui uma função pública add(a: i32, b: i32) -> i32, e o módulo greeting possui uma função pública say_hello(name: &str) -> String. Chame ambas as funções em main.
  2. Dificuldade ⭐⭐: Simule um sistema de módulos do tipo “biblioteca”. Crie o módulo library, que inclui o submódulo books (gerenciamento de livros) e o submódulo members (gerenciamento de membros). O books contém as funções add_book e list_books, e o members contém as funções add_member e list_members. Use pub(super) e pub(crate) para controlar a visibilidade adequadamente. O módulo main demonstra como adicionar livros e membros.
  3. Dificuldade ⭐⭐⭐: Explore a estrutura do projeto do espaço de trabalho do Cargo. Crie localmente um projeto de espaço de trabalho que inclua core-lib (uma biblioteca que fornece as funções add e subtract) e cli-app (um executável que realiza cálculos usando core-lib e imprime os resultados). Configure as definições do espaço de trabalho para Cargo.toml, compile-o usando cargo build --workspace e execute-o usando cargo run -p cli-app.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%