Fundamentos do Sistema de Módulos em Rust
O sistema de módulos em Rust é o alicerce da organização de código profissional. Ao contrário de outras linguagens que usam convenções de diretórios, Rust oferece controle explícito sobre visibilidade e importação através de palavras-chave dedicadas. Entender mod, pub e use é essencial para estruturar projetos escaláveis e manuteníveis.
Um módulo é um namespace que agrupa código relacionado. Pode ser definido inline em um arquivo ou em estruturas de diretório. A palavra-chave mod declara um módulo; pub controla sua visibilidade; use traz itens para o escopo atual. Juntos, esses três conceitos formam um sistema robusto de encapsulamento.
Declarando e Organizando Módulos com mod
Módulos Inline
Módulos podem ser declarados diretamente no arquivo usando blocos mod {}. Essa abordagem funciona bem para projetos pequenos ou quando o código está intimamente relacionado.
// src/main.rs
mod calculos {
pub fn somar(a: i32, b: i32) -> i32 {
a + b
}
fn subtrair(a: i32, b: i32) -> i32 {
a - b
}
}
fn main() {
let resultado = calculos::somar(5, 3);
println!("Resultado: {}", resultado);
// calculos::subtrair(5, 3) causaria erro — função privada
}
Módulos em Arquivos Separados
Para projetos maiores, organize módulos em arquivos. Rust busca automaticamente nomemodulo.rs quando você declara mod nomemodulo.
src/
├── main.rs
├── utils.rs
└── operacoes/
├── mod.rs
├── aritmetica.rs
└── logica.rs
Em src/main.rs:
mod utils;
mod operacoes;
fn main() {
let resultado = utils::formatar("Teste");
println!("{}", resultado);
}
Em src/utils.rs:
pub fn formatar(texto: &str) -> String {
format!("Formatado: {}", texto)
}
Para submódulos, crie um diretório com mod.rs que declare os submódulos:
// src/operacoes/mod.rs
pub mod aritmetica;
pub mod logica;
// src/operacoes/aritmetica.rs
pub fn multiplicar(a: i32, b: i32) -> i32 {
a * b
}
Controlando Visibilidade com pub
A visibilidade em Rust segue um princípio: tudo é privado por padrão. Você deve explicitamente tornar públicos os itens que deseja exportar. Isso evita exposição acidental e força um design consciente da API.
// src/biblioteca.rs
// Privado — não acessível fora deste módulo
struct Interno {
valor: i32,
}
// Público — acessível em qualquer lugar
pub struct Calculadora {
nome: String,
}
impl Calculadora {
// Privado — apenas para uso interno
fn validar(&self) -> bool {
true
}
// Público — faz parte da API pública
pub fn calcular(&self, x: i32) -> i32 {
if self.validar() {
x * 2
} else {
0
}
}
}
pub fn processar(entrada: &str) -> String {
format!("Processado: {}", entrada)
}
Você também pode usar pub(crate) para tornar algo público apenas dentro do crate, ou pub(in caminho) para controle mais fino:
pub(crate) fn funcao_interna() {
// Visível em todo o crate, mas não externamente
}
pub(in super) fn outra_funcao() {
// Visível apenas no módulo pai
}
Importando com use
A palavra-chave use traz itens de módulos para o escopo atual, evitando repetição de caminhos completos. Isso melhora a legibilidade significativamente em projetos reais.
Importações Simples e Nesting
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
// Equivalente a:
use std::{
collections::HashMap,
fs::File,
io::Read,
};
fn exemplo() {
let mut mapa: HashMap<String, i32> = HashMap::new();
mapa.insert("chave".to_string(), 42);
}
Importações Seletivas
Use * para importar todos os itens públicos de um módulo (com moderação):
use std::collections::*;
fn listar() {
let _mapa: HashMap<String, i32> = HashMap::new();
let _vetor: Vec<String> = Vec::new();
}
Renomeando Imports
Quando há conflitos de nomes ou para melhorar clareza:
use std::fs::File as ArquivoRust;
use std::io::Result as IoResult;
fn abrir() -> IoResult<()> {
let _arquivo = ArquivoRust::open("teste.txt")?;
Ok(())
}
Importações em Projetos Reais
// src/main.rs
mod database;
mod api;
use database::conectar;
use api::servidor::{iniciar, Configuracao};
fn main() {
let config = Configuracao::padrao();
let _conn = conectar("localhost");
iniciar(config);
}
Conclusão
Dominar o sistema de módulos em Rust é fundamental para desenvolvimento profissional. Primeiro, use mod para organizar código em namespaces lógicos — prefira arquivos separados em projetos maiores. Segundo, aplique pub conscientemente: exponha apenas o necessário e crie APIs claras e coesas. Terceiro, use use para tornar código legível, trazendo apenas os itens necessários para o escopo atual. Esses três conceitos juntos criam uma base sólida para escalabilidade e manutenção de código.