anyhow & thiserror
thiserror define erros tipados para bibliotecas. anyhow fornece tratamento ergonômico de Result para aplicações com cadeias de contexto e downcasting.
Receita
# Biblioteca crate
thiserror = "2"
# Binário / serviço crate
anyhow = "1"
thiserror = "2" # se você expõe erros tipados internamente// biblioteca
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("chave ausente: {0}")]
Missing(&'static str),
#[error(transparent)]
Io(#[from] std::io::Error),
}// binário
use anyhow::{Context, Result};
fn load() -> Result<String> {
std::fs::read_to_string("config.toml")
.context("lendo config.toml")?;
Ok(String::new())
}Quando usar isto:
- Bibliotecas: enums
thiserrorcom#[from] - CLIs e serviços:
anyhow::Resultemmaine manipuladores de nível superior
Exemplo de Trabalho
use anyhow::{Context, Result};
use thiserror::Error;
#[derive(Debug, Error)]
enum ParseError {
#[error("porta inválida: {0}")]
BadPort(u16),
}
fn parse_port(s: &str) -> Result<u16, ParseError> {
let n: u16 = s.parse().map_err(|_| ParseError::BadPort(0))?;
if n == 0 {
return Err(ParseError::BadPort(n));
}
Ok(n)
}
fn main() -> Result<()> {
let port = parse_port("8080").context("analisando a variável de ambiente PORT")?;
println!("{port}");
Ok(())
}O que isto demonstra:
- A fronteira da biblioteca retorna
ParseErrortipado - A aplicação adiciona contexto com
.context() mainretornaanyhow::Result<()>
Mergulho Profundo
Dividir por Tipo de Crate
| Tipo de Crate | Tipo de Erro | Por quê |
|---|---|---|
| Biblioteca | enum thiserror | Chamadores combinam variantes |
| Binário | anyhow::Error | Um caminho de propagação para main |
| Workspace | pub type AppError = anyhow::Error apenas no binário | Mantenha a superfície da biblioteca tipada |
Cadeias de Contexto
use anyhow::Context;
db_query().context("carregando usuários para a execução de faturamento")?;O backtrace impresso mostra a cadeia completa quando RUST_BACKTRACE=1.
Armadilhas
- anyhow em APIs públicas de bibliotecas - os chamadores não podem combinar erros. Correção: exportar tipos
thiserrorde crates de biblioteca. - Stringly
map_err(|e| e.to_string())- perde a origem. Correção:#[from]ou.context(). - Muitos enums de erro - fragmentação. Correção: um enum por módulo do crate com
#[from]. - Panicking em impls
From- esconde bugs. Correção: apenas?em conversõesFromreais. - Misturando
Box<dyn Error>- padrão desatualizado em código novo. Correção: padronizar em anyhow/thiserror.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
impl Error manual | no_std embarcado | Serviços std normais |
snafu | Erros estilo Builder | Equipe já usa thiserror |
eyre | Relatórios coloridos em CLI | Bibliotecas |
FAQs
Bibliotecas podem usar anyhow internamente?
Sim, em módulos privados, mas funções públicas devem retornar erros tipados.
Como adiciono contexto em async?
O mesmo .context() no ? - funciona entre pontos de await.
thiserror 1 vs 2?
Prefira 2 para novos projetos. Verifique o alinhamento do workspace antes de atualizar.
Handlers HTTP devem usar anyhow?
Mapeie para códigos de status na fronteira; use erros de domínio tipados dentro dos handlers.
Relacionados
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.