No description
Find a file
2026-08-14 07:24:06 +02:00
.woodpecker chore: migrate CI to .woodpecker/{push,branch}.yml 2026-08-14 07:24:06 +02:00
src fix(020): pedagogical MINOR fixes 2026-08-14 07:24:06 +02:00
tests initial content 2026-08-14 07:24:02 +02:00
.gitignore Initial commit 2026-08-14 05:23:41 +00:00
Cargo.lock initial content 2026-08-14 07:24:02 +02:00
Cargo.toml chore: declare MSRV 1.85 (edition 2024) 2026-08-14 07:24:06 +02:00
LICENSE chore: add AGPL-3.0 license and standard .gitignore 2026-08-14 07:24:06 +02:00
README.md fix(020): pedagogical MINOR fixes 2026-08-14 07:24:06 +02:00

Lição 20: Protocolos de Incerteza (Result e Tratamento de Erros)

1. Narrativa

No campo de batalha, nada é garantido. O mecha Æther enfrenta situações onde operações podem falhar — conexões perdidas, sensores danificados, energia insuficiente. Protocolos de Incerteza ensina o piloto a usar Result<T, E> para lidar com falhas de forma segura e elegante.

2. Conceito

Result<T, E> é o mecanismo de Rust para tratamento de erros recuperáveis:

  • Ok(T): Operação bem-sucedida, contém o resultado
  • Err(E): Operação falhou, contém o erro
  • ? operador: Propaga erros automaticamente
  • .unwrap(): Extrai valor ou entra em pânico (cuidado!)
  • .map() / .and_then(): Transforma resultados encadeados

3. Requisitos

  • Criar funções que retornam Result<T, E>
  • Usar o operador ? para propagação
  • Definir tipos de erro customizados

4. Design de Dados

graph LR
    A[Operação] --> B{Resultado}
    B -->|Sucesso| C[Ok: T]
    B -->|Falha| D[Err: E]
    C --> E[Usar valor]
    D --> F[Tratar erro]
    F --> G[Recuperar ou propagar]

5. Diagrama de Fluxo

flowchart TD
    A[Executar operação] --> B{Retorna Result}
    B -->|Ok| C[Valor disponível]
    B -->|Err| D{Como tratar?}
    D -->|Recuperar| E[Valor padrão / retry]
    D -->|Propagar| F[Operador ?]
    D -->|Pânico| G[unwrap / expect]
    C --> H[Continuar execução]
    E --> H
    F --> I[Chamador decide]

6. Funções

Função Descrição
dividir_seguro Divisão que retorna Result em vez de pânico
verificar_energia Verifica se energia é suficiente
conectar_sensor Simula conexão que pode falhar
parsear_inteiro Converte string para i32
validar_codigo Valida código de acesso
combinar_resultados Combina dois Results em um
obter_ou_padrao Retorna valor ou padrão em caso de erro
cadeia_operacoes Encadeia operações com propagação

7. Exemplo

fn dividir(a: i32, b: i32) -> Result<i32, &'static str> {
    if b == 0 {
        Err("Divisão por zero")
    } else {
        Ok(a / b)
    }
}

fn executar() -> Result<i32, &'static str> {
    let resultado = dividir(10, 2)?;
    Ok(resultado)
}

assert_eq!(executar(), Ok(5));

8. Missão

  1. Implementar dividir_seguro retornando Result<i32, &str>
  2. Implementar verificar_energia com Result para energia insuficiente
  3. Implementar conectar_sensor simulando falha de conexão
  4. Implementar parsear_inteiro usando .parse() com Result
  5. Implementar validar_codigo verificando formato do código
  6. Implementar combinar_resultados juntando dois Results
  7. Implementar obter_ou_padrao com .unwrap_or()
  8. Implementar cadeia_operacoes usando o operador ? — como a função retorna Result<i32, &'static str> e .parse() produz ParseIntError, use .map_err(|_| "erro") para converter o erro antes de aplicar ?

9. Como Executar

cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check

10. Dicas

  • Result<T, E> é um enum: Ok(valor) ou Err(erro)
  • O operador ? propaga erros — só funciona em funções que retornam Result
  • ? converte o erro automaticamente apenas quando existe impl From<ErroOrigem> for ErroDestino. Como ParseIntError não converte para &'static str, use .map_err(|_| "erro") antes do ? em cadeia_operacoes
  • Prefira ? e .unwrap_or() a .unwrap() direto
  • Erros customizados podem implementar std::error::Error
  • Avançado (Lição 28): combinar_resultados<T, E> usa parâmetros genéricos <T, E> — você verá generics em detalhe na Lição 28. Por ora, trate T e E como "qualquer tipo" que o chamador escolher