thiserror — это лёгкая библиотека, предоставляющая производный макрос для упрощения определения ошибок.
Особенности:
Лаконичный синтаксис с минимальным boilerplate
Идеально подходит для создания библиотек типов ошибок и API
Чаще используется при создании библиотек для других разработчиков
usethiserror::Error;#[derive(Error, Debug)]pubenumDataError{#[error("Ошибка базы данных: {0}")]DatabaseError(#[from]sqlx::Error),#[error("Ошибка валидации: {0}")]ValidationError(String),#[error("Запись не найдена")]NotFound,}
snafu предлагает более комплексный фреймворк обработки ошибок с акцентом на контекст и цепочки ошибок.
Особенности:
Поощряет точное добавление контекста через паттерн "селекторов контекста"
Рекомендует подход "одно перечисление ошибок на модуль"
Поддерживает варианты ошибок в виде структур и кортежей
Встроенная поддержка трассировки стека
usesnafu::{Snafu,ResultExt,Backtrace};#[derive(Debug, Snafu)]pubenumError{#[snafu(display("Не удалось прочитать конфигурационный файл {filename:?}"))]ReadConfig{ filename:String, source:std::io::Error, backtrace:Backtrace,},// Также поддерживается стиль кортежей#[snafu(display("Ошибка ввода-вывода"))]Io(#[snafu(source)]std::io::Error,#[snafu(backtrace)]Backtrace),}// Пример использования селектора контекстаfnread_config(path:&str)->Result<Config,Error>{std::fs::read_to_string(path).context(ReadConfigSnafu{ filename: path })?;// ...}
anyhow принципиально отличается от предыдущих библиотек, фокусируясь на приложениях, а не библиотеках.
Особенности:
Разработан для обработки ошибок в приложениях, а не библиотеках
Предоставляет динамический тип anyhow::Error, который может содержать любую ошибку, реализующую трейт Error
Упрощает обработку ошибок разных типов
Не требует определения пользовательских типов ошибок
useanyhow::{Context,Result};fnmain()->Result<()>{let config =std::fs::read_to_string("config.json").context("Не удалось прочитать конфигурационный файл")?;let app_config:AppConfig=serde_json::from_str(&config).context("Недопустимый формат конфигурации")?;// Используем Result<T> как псевдоним для Result<T, anyhow::Error>Ok(())}
anyhow vs thiserror/snafu:
anyhow ориентирован на быструю разработку приложений
thiserror/snafu фокусируются на создании точных иерархий типов ошибок
anyhow обычно используется в коде приложений
thiserror/snafu обычно применяются в библиотеках
На практике anyhow и thiserror часто используются вместе: библиотеки определяют точные типы ошибок через thiserror, а приложения обрабатывают разнородные ошибки через anyhow.