Tratamento de erros em Rust: try/catch e além — guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Tratamento de erros em Rust: abandonando try/catch em prol da segurança



Ao contrário de Python ou Java, Rust não possui a construção clássica try/catch. Os desenvolvedores da linguagem seguiram outro caminho, tornando o tratamento de erros parte do sistema de tipos. Isso não é um capricho, mas uma decisão fundamental que permite garantir a segurança da memória e a previsibilidade da execução do programa em tempo de compilação. Neste artigo, abordaremos todas as formas de tratamento de erros em Rust: desde os básicos Result e Option até métodos avançados com o operador ? e tipos de erro personalizados.



1. Dois tipos principais: Result e Option



Em Rust, todos os erros são divididos em duas categorias: recuperáveis (tratados através de Result) e irrecuperáveis (que levam a panic!). Existe também o tipo Option para casos em que um valor pode estar ausente.



Tipo Result



Result<T, E> é uma enumeração (enum) que pode ser Ok(T) (sucesso com dados) ou Err(E) (erro com descrição). Esta é a ferramenta principal para tratar erros esperados: erros de entrada/saída, parsing, requisições de rede.



use std::fs::File;use std::io::Read;

fn read_file_content(path: &str) -> Result<String, std::io::Error> { let mut file = File::open(path)?; let mut content = String::new(); file.read_to_string(&mut content)?; Ok(content)}


Tipo Option



Option<T> é outro enum que assume os valores Some(T) (valor existe) ou None (valor não existe). É usado quando a ausência de dados é uma situação normal, e não um erro.



fn find_user(id: u32) -> Option<String> {    let users = vec!["Alice".to_string(), "Bob".to_string()];    users.get(id as usize).cloned()}

fn main() { match find_user(0) { Some(name) => println!("Usuário encontrado: {}", name), None => println!("Usuário não encontrado"), }}


2. Operador ? — substituição elegante para try/catch



Se Rust tivesse try/catch, ele seria verboso. Em vez disso, a linguagem oferece o operador ?. Ele funciona assim: se o resultado for Ok, o valor é extraído e passado adiante; se for Err, o erro é imediatamente retornado da função.



use std::num::ParseIntError;

fn parse_and_double(input: &str) -> Result<i32, ParseIntError> { let value: i32 = input.parse()?; // se erro — retorna Err imediatamente Ok(value * 2)}

fn main() { match parse_and_double("42") { Ok(result) => println!("Resultado: {}", result), Err(e) => println!("Erro de parsing: {}", e), }}


O operador ? só pode ser usado em funções que retornam Result ou Option. Isso força o desenvolvedor a indicar explicitamente que a função pode falhar — ao contrário das exceções em Python, que podem "surgir" de qualquer lugar.



3. Quando usar panic! e unwrap



Nem todos os erros precisam ser tratados. panic! é uma macro para erros irrecuperáveis. Ela interrompe o programa e desenrola a pilha (stack unwind). Use-a apenas em situações excepcionais:



  • Estados críticos: violação de invariantes que não podem ser corrigidos.
  • Exemplos e protótipos: em código educacional ou scripts descartáveis.
  • Testes: para verificar se o código falha nos lugares esperados.


fn divide(a: i32, b: i32) -> i32 {    if b == 0 {        panic!("Divisão por zero! a={}, b={}", a, b);    }    a / b}


unwrap() e expect()

Blogs

Book Recommendations