---
title: "Sistema de Módulos Rust: mod, use, Crates | Rust Brasil"
url: "https://rustlang.com.br/artigos/sistema-modulos/"
markdown_url: "https://rustlang.com.br/artigos/sistema-modulos.MD"
description: "Guia do sistema de módulos em Rust: mod, use, pub, re-exports, paths, mod.rs e organização de workspaces com Cargo."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Sistema de Módulos Rust: mod, use, Crates | Rust Brasil

Guia do sistema de módulos em Rust: mod, use, pub, re-exports, paths, mod.rs e organização de workspaces com Cargo.


O sistema de módulos do Rust é poderoso, mas pode ser confuso para iniciantes — especialmente quem vem de linguagens onde a estrutura de arquivos determina automaticamente os módulos. Em Rust, a hierarquia de módulos é **explícita**: você precisa declarar cada módulo e suas relações. Neste artigo, vamos desmistificar `mod`, `use`, `pub` e a organização de projetos, desde um arquivo único até workspaces multi-crate.

## Conceitos Fundamentais

### Crate, Módulo e Path

```
Hierarquia do sistema de módulos:
──────────────────────────────────
Crate (unidade de compilação)
  └── Módulo raiz (lib.rs ou main.rs)
      ├── Módulo A
      │   ├── Submódulo A1
      │   └── Submódulo A2
      └── Módulo B
          └── Submódulo B1

Paths (caminhos para itens):
  crate::modulo_a::submodulo_a1::funcao()
  self::funcao_local()
  super::funcao_do_pai()
```

- **Crate**: a unidade de compilação — um binário ou uma biblioteca
- **Módulo**: um namespace que agrupa itens relacionados
- **Path**: o caminho para acessar um item (`crate::modulo::item`)

## Módulos Inline

A forma mais simples de criar módulos: declarar diretamente no arquivo:

```rust
mod matematica {
    pub fn somar(a: i32, b: i32) -> i32 {
        a + b
    }

    pub fn multiplicar(a: i32, b: i32) -> i32 {
        a * b
    }

    // Função privada — não acessível fora do módulo
    fn auxiliar() -> i32 {
        42
    }

    // Submódulo
    pub mod avancado {
        pub fn potencia(base: f64, exp: u32) -> f64 {
            (0..exp).fold(1.0, |acc, _| acc * base)
        }
    }
}

fn main() {
    println!("{}", matematica::somar(2, 3));
    println!("{}", matematica::multiplicar(4, 5));
    println!("{}", matematica::avancado::potencia(2.0, 10));

    // matematica::auxiliar(); // ERRO: função privada
}
```

## Módulos em Arquivos Separados

Para projetos maiores, cada módulo vai em seu próprio arquivo. Existem duas convenções:

### Convenção Moderna (Rust 2018+): Arquivo por Módulo

```
meu_projeto/
├── Cargo.toml
└── src/
    ├── main.rs
    ├── config.rs         ← módulo config
    ├── database.rs       ← módulo database
    └── handlers/
        ├── mod.rs        ← módulo handlers (raiz)
        ├── usuarios.rs   ← submódulo handlers::usuarios
        └── produtos.rs   ← submódulo handlers::produtos
```

Ou a alternativa sem `mod.rs` (recomendada para novos projetos):

```
meu_projeto/
├── Cargo.toml
└── src/
    ├── main.rs
    ├── config.rs
    ├── database.rs
    ├── handlers.rs       ← declara submódulos
    └── handlers/
        ├── usuarios.rs
        └── produtos.rs
```

### Implementação

**`src/main.rs`:**
```rust
mod config;
mod database;
mod handlers;

fn main() {
    let cfg = config::carregar();
    println!("Porta: {}", cfg.porta);

    database::inicializar(&cfg);

    handlers::usuarios::listar();
    handlers::produtos::listar();
}
```

**`src/config.rs`:**
```rust
pub struct Config {
    pub porta: u16,
    pub host: String,
    pub database_url: String,
}

pub fn carregar() -> Config {
    Config {
        porta: 8080,
        host: "localhost".to_string(),
        database_url: "postgres://localhost/app".to_string(),
    }
}
```

**`src/database.rs`:**
```rust
use crate::config::Config;

pub fn inicializar(config: &Config) {
    println!("Conectando ao banco: {}", config.database_url);
}

pub fn executar_query(sql: &str) -> Vec<String> {
    println!("Executando: {}", sql);
    vec!["resultado1".to_string(), "resultado2".to_string()]
}
```

**`src/handlers.rs`** (declara submódulos):
```rust
pub mod usuarios;
pub mod produtos;
```

**`src/handlers/usuarios.rs`:**
```rust
use crate::database;

pub fn listar() {
    let resultados = database::executar_query("SELECT * FROM usuarios");
    println!("Usuários: {:?}", resultados);
}

pub fn buscar_por_id(id: u32) -> Option<String> {
    let resultados = database::executar_query(&format!("SELECT * FROM usuarios WHERE id = {}", id));
    resultados.into_iter().next()
}
```

**`src/handlers/produtos.rs`:**
```rust
use crate::database;

pub fn listar() {
    let resultados = database::executar_query("SELECT * FROM produtos");
    println!("Produtos: {:?}", resultados);
}
```

## Visibilidade: `pub` e Suas Variantes

O Rust tem um sistema de visibilidade granular:

```rust
mod externo {
    pub mod interno {
        // pub — visível para todos
        pub fn publica() {}

        // (sem pub) — visível apenas dentro deste módulo
        fn privada() {}

        // pub(crate) — visível em qualquer lugar DENTRO do crate
        pub(crate) fn interna_crate() {}

        // pub(super) — visível no módulo pai
        pub(super) fn interna_pai() {}

        // pub(in crate::externo) — visível no caminho especificado
        pub(in crate::externo) fn interna_externo() {}
    }

    pub fn usar_interno() {
        interno::publica();           // OK
        // interno::privada();        // ERRO: privada
        interno::interna_crate();     // OK: mesmo crate
        interno::interna_pai();       // OK: somos o super
        interno::interna_externo();   // OK: estamos em crate::externo
    }
}

fn main() {
    externo::interno::publica();       // OK
    // externo::interno::privada();    // ERRO
    externo::interno::interna_crate(); // OK: mesmo crate
    // externo::interno::interna_pai(); // ERRO: não somos o super
}
```

### Structs com Campos Privados

```rust
mod banco {
    pub struct ContaBancaria {
        titular: String,         // privado!
        pub numero: u64,
        saldo: f64,              // privado!
    }

    impl ContaBancaria {
        // Construtor público necessário porque campos são privados
        pub fn nova(titular: &str, numero: u64) -> Self {
            ContaBancaria {
                titular: titular.to_string(),
                numero,
                saldo: 0.0,
            }
        }

        pub fn titular(&self) -> &str {
            &self.titular
        }

        pub fn saldo(&self) -> f64 {
            self.saldo
        }

        pub fn depositar(&mut self, valor: f64) {
            if valor > 0.0 {
                self.saldo += valor;
            }
        }
    }
}

fn main() {
    let mut conta = banco::ContaBancaria::nova("Ana", 12345);
    conta.depositar(1000.0);

    println!("Conta {}: titular={}, saldo=R${:.2}",
        conta.numero,       // OK: campo público
        conta.titular(),    // OK: método público
        conta.saldo(),      // OK: método público
    );
    // conta.saldo = -100.0; // ERRO: campo privado
}
```

## `use` — Importando Itens

### Básico

```rust
// Caminho completo — verboso
fn exemplo1() {
    let mapa = std::collections::HashMap::<String, i32>::new();
    println!("{:?}", mapa);
}

// Com use — limpo
use std::collections::HashMap;

fn exemplo2() {
    let mapa = HashMap::<String, i32>::new();
    println!("{:?}", mapa);
}

fn main() {
    exemplo1();
    exemplo2();
}
```

### Importações Múltiplas e Aninhadas

```rust
// Importar múltiplos itens do mesmo módulo
use std::collections::{HashMap, HashSet, BTreeMap};

// Importar com renomeação (alias)
use std::collections::HashMap as Mapa;
use std::io::Result as IoResult;

// Importar tudo de um módulo (use com cautela)
// use std::collections::*;

// Importações aninhadas
use std::io::{self, Read, Write, BufRead};
// Equivalente a:
// use std::io;
// use std::io::Read;
// use std::io::Write;
// use std::io::BufRead;

fn main() {
    let _: HashMap<String, i32> = HashMap::new();
    let _: HashSet<i32> = HashSet::new();
    let _: BTreeMap<String, i32> = BTreeMap::new();
    let _: Mapa<String, i32> = Mapa::new();
}
```

### Convenções de Importação

```rust
// CONVENÇÃO: importar o módulo pai para funções
use std::fmt;
// Uso: fmt::Display, fmt::Formatter

// CONVENÇÃO: importar o tipo diretamente para structs/enums/traits
use std::collections::HashMap;
// Uso: HashMap::new()

// CONVENÇÃO: re-exportar no nível adequado
mod modelos {
    pub mod usuario {
        pub struct Usuario {
            pub nome: String,
        }
    }
}

// Re-exportar para simplificar o acesso
pub use modelos::usuario::Usuario;

fn main() {
    let u = Usuario { nome: "Ana".into() };
    println!("{}", u.nome);
}
```

## Resolução de Paths

### `crate`, `self`, `super`

```rust
mod nivel1 {
    pub fn funcao_nivel1() -> &'static str {
        "nível 1"
    }

    pub mod nivel2 {
        pub fn funcao_nivel2() -> &'static str {
            "nível 2"
        }

        // super:: refere-se ao módulo pai (nivel1)
        pub fn chamar_pai() -> &'static str {
            super::funcao_nivel1()
        }

        pub mod nivel3 {
            // crate:: começa da raiz do crate
            pub fn chamar_raiz() {
                println!("{}", crate::nivel1::funcao_nivel1());
            }

            // super:: vai um nível acima (nivel2)
            pub fn chamar_nivel2() {
                println!("{}", super::funcao_nivel2());
            }

            // super::super:: vai dois níveis acima (nivel1)
            pub fn chamar_nivel1() {
                println!("{}", super::super::funcao_nivel1());
            }

            // self:: refere-se ao módulo atual
            pub fn local() -> &'static str {
                "nível 3"
            }

            pub fn chamar_local() {
                println!("{}", self::local());
            }
        }
    }
}

fn main() {
    nivel1::nivel2::nivel3::chamar_raiz();
    nivel1::nivel2::nivel3::chamar_nivel2();
    nivel1::nivel2::nivel3::chamar_nivel1();
    nivel1::nivel2::nivel3::chamar_local();
}
```

## Re-exports: Organizando a API Pública

Re-exports (`pub use`) permitem criar uma API pública limpa independente da estrutura interna:

```rust
// Estrutura interna complexa
mod internos {
    pub mod v2 {
        pub mod processamento {
            pub struct Processador {
                pub nome: String,
            }

            impl Processador {
                pub fn novo(nome: &str) -> Self {
                    Processador { nome: nome.to_string() }
                }

                pub fn executar(&self) {
                    println!("Processador '{}' executando", self.nome);
                }
            }
        }

        pub mod erros {
            #[derive(Debug)]
            pub enum AppError {
                NaoEncontrado,
                Permissao,
            }
        }
    }
}

// Re-exports criam uma API pública limpa
pub use internos::v2::processamento::Processador;
pub use internos::v2::erros::AppError;

fn main() {
    // Usuários usam o caminho curto
    let p = Processador::novo("principal");
    p.executar();

    let _erro = AppError::NaoEncontrado;

    // Em vez de:
    // let p = internos::v2::processamento::Processador::novo("principal");
}
```

### Padrão Prelude

Muitas bibliotecas usam um módulo `prelude` para re-exportar os itens mais usados:

```rust
mod tipos {
    pub struct Config {
        pub valor: String,
    }

    pub struct Conexao {
        pub url: String,
    }

    pub trait Executavel {
        fn executar(&self);
    }
}

mod erros {
    #[derive(Debug)]
    pub enum Erro {
        Conexao,
        Timeout,
    }

    pub type Resultado<T> = Result<T, Erro>;
}

// Prelude: re-exporta tudo que o usuário geralmente precisa
pub mod prelude {
    pub use crate::tipos::{Config, Conexao, Executavel};
    pub use crate::erros::{Erro, Resultado};
}

// Uso:
use crate::prelude::*;

impl Executavel for Config {
    fn executar(&self) {
        println!("Executando config: {}", self.valor);
    }
}

fn main() {
    let config = Config { valor: "teste".into() };
    config.executar();

    let resultado: Resultado<i32> = Ok(42);
    println!("{:?}", resultado);
}
```

## Workspaces: Projetos Multi-Crate

Para projetos grandes, o Cargo suporta **workspaces** — múltiplos crates que compartilham um `Cargo.lock`:

### Estrutura

```
meu_workspace/
├── Cargo.toml              ← workspace root
├── crates/
│   ├── core/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── lib.rs
│   ├── api/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   └── cli/
│       ├── Cargo.toml
│       └── src/
│           └── main.rs
└── shared/
    ├── Cargo.toml
    └── src/
        └── lib.rs
```

### Configuração

**`Cargo.toml` (raiz do workspace):**
```toml
[workspace]
members = [
    "crates/core",
    "crates/api",
    "crates/cli",
    "shared",
]

# Dependências compartilhadas por todos os membros
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
```

**`crates/core/Cargo.toml`:**
```toml
[package]
name = "meu-core"
version = "0.1.0"
edition = "2021"

[dependencies]
serde.workspace = true  # usa a versão do workspace
```

**`crates/api/Cargo.toml`:**
```toml
[package]
name = "meu-api"
version = "0.1.0"
edition = "2021"

[dependencies]
meu-core = { path = "../core" }  # dependência local
tokio.workspace = true
serde.workspace = true
```

### Comandos Úteis

```bash
# Compilar todo o workspace
cargo build

# Compilar apenas um crate
cargo build -p meu-api

# Rodar testes de todo o workspace
cargo test

# Rodar testes de um crate específico
cargo test -p meu-core

# Rodar o binário de um crate
cargo run -p meu-api
cargo run -p meu-cli
```

## Padrão de Organização Recomendado

Para projetos de médio porte, esta é uma organização robusta:

```
meu_projeto/
├── Cargo.toml
├── src/
│   ├── main.rs           ← ponto de entrada, setup e coordenação
│   ├── lib.rs            ← API pública da biblioteca (opcional)
│   ├── config.rs         ← carregamento de configuração
│   ├── error.rs          ← tipos de erro customizados
│   ├── models/
│   │   ├── mod.rs
│   │   ├── usuario.rs
│   │   └── produto.rs
│   ├── services/
│   │   ├── mod.rs
│   │   ├── auth.rs
│   │   └── pedidos.rs
│   ├── handlers/         ← (para web: endpoints HTTP)
│   │   ├── mod.rs
│   │   ├── api.rs
│   │   └── health.rs
│   └── db/
│       ├── mod.rs
│       ├── pool.rs
│       └── queries.rs
├── tests/                ← testes de integração
│   └── api_test.rs
└── benches/              ← benchmarks
    └── performance.rs
```

**`src/main.rs`:**
```rust
mod config;
mod error;
mod models;
mod services;
mod handlers;
mod db;

// Re-exports para uso fácil
use error::AppError;

fn main() -> Result<(), AppError> {
    let cfg = config::carregar()?;
    println!("Servidor iniciando na porta {}", cfg.porta);
    Ok(())
}
```

**`src/error.rs`:**
```rust
use std::fmt;

#[derive(Debug)]
pub enum AppError {
    Config(String),
    Database(String),
    NotFound(String),
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            AppError::Config(msg) => write!(f, "Erro de configuração: {}", msg),
            AppError::Database(msg) => write!(f, "Erro de banco: {}", msg),
            AppError::NotFound(msg) => write!(f, "Não encontrado: {}", msg),
        }
    }
}

impl std::error::Error for AppError {}
```

**`src/models/mod.rs`:**
```rust
pub mod usuario;
pub mod produto;

// Re-exports dos tipos principais
pub use usuario::Usuario;
pub use produto::Produto;
```

## Erros Comuns

### 1. Unresolved Import

```rust
// ERRO: mod 'utils' não foi declarado
// use crate::utils::helper;

// SOLUÇÃO: declare o módulo em main.rs ou lib.rs
// mod utils; // ← adicionar isso
```

Veja [Cargo: Unresolved Import](/erros/cargo-unresolved-import/) para mais detalhes.

### 2. Esquecer `pub` em itens exportados

```rust
mod meu_modulo {
    // ERRO: struct é pública mas campo é privado
    // pub struct Config {
    //     porta: u16, // privado!
    // }

    // CORRETO
    pub struct Config {
        pub porta: u16,
    }
}

fn main() {
    let c = meu_modulo::Config { porta: 8080 };
    println!("{}", c.porta);
}
```

### 3. Confusão entre `mod.rs` e arquivo com nome do módulo

```
// Ambos representam o módulo 'handlers':

// Opção 1: handlers/mod.rs
src/
├── handlers/
│   └── mod.rs

// Opção 2: handlers.rs (+ pasta handlers/ para submódulos)
src/
├── handlers.rs
├── handlers/
│   └── sub.rs

// NÃO PODE ter ambos — é um erro de compilação!
```

### 4. Caminho circular

```rust
// ERRO: módulos não podem ter dependências circulares
// mod a { use crate::b::funcao_b; }
// mod b { use crate::a::funcao_a; }

// SOLUÇÃO: extraia a parte compartilhada para um módulo separado
mod compartilhado {
    pub fn funcao_compartilhada() {}
}

mod a {
    use crate::compartilhado;

    pub fn funcao_a() {
        compartilhado::funcao_compartilhada();
    }
}

mod b {
    use crate::compartilhado;

    pub fn funcao_b() {
        compartilhado::funcao_compartilhada();
    }
}

fn main() {
    a::funcao_a();
    b::funcao_b();
}
```

## Veja Também

- [Cargo: Unresolved Import](/erros/cargo-unresolved-import/) — como resolver erros de importação
- [Instalação e Configuração do Cargo](/instalacao/cargo/) — gerenciamento de dependências
- [Traits e Generics em Rust](/tutoriais/traits-generics/) — organização de traits em módulos
- [Macros em Rust](/artigos/macros-rust/) — macros e sistema de módulos
- [Unsafe Rust](/artigos/unsafe-rust/) — módulos para encapsular código unsafe

---

Se você quer comparar sistemas de módulos entre linguagens, veja também:

- <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go Packages: o sistema de pacotes e módulos de Go</a>
- <a href="https://python.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">Módulos Python: imports, pacotes e organização de código em Python</a>
- <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin Packages: organização de código e visibilidade em Kotlin</a>
