thiserror and anyhow

The thiserror and anyhow crates are widely used to simplify error handling.

  • thiserror is often used in libraries to create custom error types that implement From<T>.
  • anyhow is often used by applications to help with error handling in functions, including adding contextual information to your errors.
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

  • The Error derive macro is provided by thiserror, and has lots of useful attributes to help define error types in a compact way.
  • The std::error::Error trait is derived automatically.
  • The message from #[error] is used to derive the Display trait.

anyhow

  • anyhow::Error๋Š” Box<dyn Error>์˜ ๋ž˜ํผ ํƒ€์ž…์ด๋ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ณต๊ฐœ API๋กœ์„œ ์‚ฌ์šฉํ•˜๊ธฐ์— ๋ถ€์ ํ•ฉํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งŽ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • anyhow::Result<V>๋Š” Result<V, anyhow::Error>์˜ ํƒ€์ž… ์•จ๋ฆฌ์–ด์Šค(alias)์ž…๋‹ˆ๋‹ค.
  • ํ•„์š”ํ•˜๋‹ค๋ฉด anyhow::Error์— ์ €์žฅ๋œ ์ง„์งœ ์—๋Ÿฌ ํƒ€์ž…์„ ๊บผ๋‚ด์–ด ๊ฒ€์‚ฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
  • anyhow::Result<T>๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์ด Go ์–ธ์–ด ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ๋Š” ์ต์ˆ™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Go์–ธ์–ด์—์„œ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” (T, error) ํŒจํ„ด๊ณผ ๋น„์Šทํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • anyhow::Context is a trait implemented for the standard Result and Option types. use anyhow::Context is necessary to enable .context() and .with_context() on those types.