Capítulo 14: Tratamento de Erros (Option e Result) 🤠💎
Neste capítulo, vamos aprender como o Rust lida com erros sem usar exceções (como o try/catch de outras linguagens), usando os tipos Option e Result, com o tema Indiana Jones!
📖 O que são Option e Result?
No Rust, não existe o valor null (nulo) para evitar o famoso erro de “ponteiro nulo”. Em vez disso, o Rust usa duas enums especiais:
Option<T>: Usado quando algo pode ou não ter um valor. Tem as variantesSome(valor)eNone(nada).Result<T, E>: Usado quando uma operação pode dar certo ou dar erro. Tem as variantesOk(valor)eErr(erro).
📖 Exemplo Guiado: Em busca do Santo Graal (Option)
Vamos criar uma função que busca um tesouro em uma lista. Se encontrar, retorna Some, se não, retorna None.
- Crie o arquivo
busca_tesouro.rsna pastasrc/:
fn buscar_tesouro(id: i32) -> Option<String> {
if id == 7 {
Some(String::from("Santo Graal"))
} else {
None // Não encontrou nada
}
}
fn main() {
let tentativa1 = buscar_tesouro(5);
let tentativa2 = buscar_tesouro(7);
// Usando match para tratar o Option
match tentativa1 {
Some(tesouro) => println!("Indiana Jones encontrou o {}!", tesouro),
None => println!("Tentativa 1: Apenas poeira..."),
}
match tentativa2 {
Some(tesouro) => println!("Indiana Jones encontrou o {}!", tesouro),
None => println!("Tentativa 2: Apenas poeira..."),
}
}🕹️ Como Executar e Testar no VS Code
- Abra le terminal integrado.
- Compile:
rustc busca_tesouro.rs - Execute:
./busca_tesouro
Resultado Esperado:
Tentativa 1: Apenas poeira...
Indiana Jones encontrou o Santo Graal!📊 Ilustração Visual: O Tipo Option
Veja como o Rust nos obriga a tratar a ausência de valor:
graph TD A[Função buscar_tesouro] -->|Sucesso| B["Some('Santo Graal')"] A -->|Falha| C[None]
🛠️ Prática Obrigatória 1: Desarmando Armadilhas (Result)
Crie uma função chamada desarmar_armadilha(codigo: i32) -> Result<String, String>. Se o código for 1234, retorne Ok com a mensagem “Armadilha desarmada!“. Se for qualquer outro número, retorne Err com a mensagem “CABUM! A armadilha disparou!“. Teste os dois casos na main usando match.
🔑 Gabarito de Código
Prática 1: armadilha_result.rs
fn desarmar_armadilha(codigo: i32) -> Result<String, String> {
if codigo == 1234 {
Ok(String::from("Armadilha desarmada!"))
} else {
Err(String::from("CABUM! A armadilha disparou!"))
}
}
fn main() {
let tentativa = desarmar_armadilha(9999);
match tentativa {
Ok(msg) => println!("Sucesso: {}", msg),
Err(erro) => println!("Erro: {}", erro),
}
}