anyhow
Крейт anyhow
надає багатий тип помилок з підтримкою передачі додаткової контекстної інформації, яка може бути використана для семантичного відстеження дій програми, що призвели до виникнення помилки.
Це можна поєднати зі зручними макросами з thiserror
, щоб уникнути написання реалізацій трейтів явно для користувацьких типів помилок.
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.
anyhow::Error
по суті є обгорткою навколоBox<dyn Error>
. Таким чином, це знову ж таки, як правило, не є хорошим вибором для загальнодоступного API бібліотеки, але широко використовується в програмах.anyhow::Result<V>
— це псевдонім типу дляResult<V, anyhow::Error>
.- Функціональність, яку надає
anyhow::Error
, може бути знайома розробникам Go, оскільки вона забезпечує поведінку, подібну до типу Goerror
, аResult<T, anyhow::Error>
дуже схожа на Go(T, error)
(з умовою, що тільки один елемент пари є значущим). anyhow::Context
- це трейт, реалізований для стандартних типівResult
таOption
. Використанняanyhow::Context
необхідне для того, щоб дозволити використання.context()
та.with_context()
для цих типів.
Більше інформації для вивчення
anyhow::Error
має підтримку даункастингу, подібно доstd::any::Any
; конкретний тип помилки, що зберігається всередині, може бути витягнутий для вивчення за допомогоюError::downcast
.