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
```html

Introdução: por que Rust não usa try/catch?

Na maioria das linguagens de programação (JavaScript, Python, Java), o tratamento de erros é baseado no mecanismo de exceções e na construção try/catch. No entanto, em Rust, essa abordagem está ausente. Em vez disso, os desenvolvedores usam um poderoso sistema de tipos, que torna os erros parte da assinatura da função. Isso não é um acaso, mas uma decisão arquitetônica bem pensada: Rust busca previsibilidade e segurança em tempo de compilação, excluindo falhas ocultas do programa.

Neste artigo, vamos abordar:

  • Por que Rust abandonou o try/catch;
  • Como funcionam as principais ferramentas: Option, Result, unwrap(), expect();
  • O que é o operador ? (ponto de interrogação);
  • Quando usar panic! e a macro try! (obsoleta);
  • Práticas modernas de tratamento de erros em Rust 2024.

1. Fundamentos: Option e Result — os dois principais tipos

Tipo Option: quando um valor pode estar ausente

Option<T> é uma enumeração (enum) que representa ou um valor (Some(T)) ou sua ausência (None). Ele é ideal para situações em que um erro no sentido clássico não ocorre, mas o resultado pode ser vazio.

fn encontrar_usuario(id: u32) -> Option<String> {
    let banco = vec!["Alice".to_string(), "Bob".to_string()];
    if id < banco.len() {
        Some(banco[id].clone())
    } else {
        None
    }
}

fn main() {
    match encontrar_usuario(1) {
        Some(nome) => println!("Encontrado: {}", nome),
        None => println!("Usuário não encontrado"),
    }
}

Tipo Result: sucesso ou erro

Result<T, E> é a ferramenta principal para tratamento de erros. Ele também é um enum: Ok(T) (sucesso) ou Err(E) (erro).

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

fn ler_arquivo(caminho: &str) -> Result<String, std::io::Error> {
    let mut arquivo = File::open(caminho)?;
    let mut conteudo = String::new();
    arquivo.read_to_string(&mut conteudo)?;
    Ok(conteudo)
}

2. Operador ? (ponto de interrogação) — substituto do try/catch

O operador ? é a principal forma de propagar erros para cima em Rust. Ele substitui construções match verbosas e torna o código limpo. Se o resultado for Ok, o valor é extraído e atribuído à variável. Se for Err, a função retorna imediatamente esse erro.

use std::fs;
use std::io;

fn copiar_arquivo(origem: &str, destino: &str) -> io::Result<()> {
    let dados = fs::read(origem)?; // se erro — saída
    fs::write(destino, &dados)?;  // se erro — saída
    Ok(())
}

fn main() -> io::Result<()> {
    copiar_arquivo("source.txt", "dest.txt")?;
    println!("Arquivo copiado com sucesso");
    Ok(())
}

Importante: o operador ? funciona apenas em funções que retornam Result, Option ou tipos que implementam a trait FromResidual.

3. panic!, unwrap e expect — quando o erro é fatal

Macro panic!

panic!() causa o encerramento abrupto do programa (stack unwinding). É usado apenas em situações onde a continuação da execução é impossível ou sem sentido: erros na lógica do programa, violação de invariantes, testes.

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

Métodos unwrap() e expect()

unwrap() é uma forma rápida de obter o valor de um Option ou Result. Se houver None ou Err internamente — pro ```

Blogs

Book Recommendations