thiserror
та anyhow
Крейти thiserror та anyhow
широко використовуються для спрощення обробки помилок.
thiserror
часто використовується у бібліотеках для створення користувацьких типів помилок, які реалізуютьFrom<T>
.anyhow
часто використовується програмами для полегшення обробки помилок у функціях, зокрема для додавання контекстної інформації до ваших помилок.
use anyhow::{bail, Context, Result}; use std::fs; use std::io::Read; use thiserror::Error; #[derive(Clone, Debug, Eq, Error, PartialEq)] #[error("Не знайдено імені користувача в {0}")] struct EmptyUsernameError(String); fn read_username(path: &str) -> Result<String> { let mut username = String::with_capacity(100); fs::File::open(path) .with_context(|| format!("Не вдалося відкрити {path}"))? .read_to_string(&mut username) .context("Не вдалося прочитати")?; if username.is_empty() { bail!(EmptyUsernameError(path.to_string())); } Ok(username) } fn main() { //fs::write("config.dat", "").unwrap(); match read_username("config.dat") { Ok(username) => println!("Ім'я користувача: {username}"), Err(err) => println!("Помилка: {err:?}"), } }
This slide should take about 5 minutes.
thiserror
- Похідний макрос
Error
надаєтьсяthiserror
і має багато корисних атрибутів для компактного визначення типів помилок. - Трейт
std::error::Error
виводиться автоматично. - Повідомлення з
#[error]
використовується для отримання трейтуDisplay
.
anyhow
anyhow::Error
по суті є обгорткою навколоBox<dyn Error>
. Таким чином, це знову ж таки, як правило, не є хорошим вибором для загальнодоступного API бібліотеки, але широко використовується в програмах.anyhow::Result<V>
— це псевдонім типу дляResult<V, anyhow::Error>
.- Фактичний тип помилки всередині нього можна вилучити для перевірки, якщо це необхідно.
- Функціональність, яку надає
anyhow::Result<T>
, може бути знайома розробникам Go, оскільки вона забезпечує подібні моделі використання та ергономіку до(T, error)
від Go. anyhow::Context
- це трейт, реалізований для стандартних типівResult
таOption
. Використанняanyhow::Context
необхідне для того, щоб дозволити використання.context()
та.with_context()
для цих типів.