anyhowメモ
anyhowのメリット
- エラーに説明を追加できる
- anyhow::Result<T>は、エラーの伝播ルートをスタックトレースとして出力してくれる
anyhowがない場合
Result<T, E>
と std::error::Error
トレイトを使う。
fn count_words<R: Read>(input: &mut R) -> Result<u32, Box<dyn Error>> { let reader = BufReader::new(input); let mut wordcount = 0; for line in reader.lines() { // line = Result<String> for _word in line?.split_whitespace() { wordcount += 1; } } Ok(wordcount) } fn main() -> Result<(), Box<dyn Error>> { // 複数ファイル対応 for filename in env::args().skip(1).collect::<Vec<String>>() { // どのファイルが開けなかったのか出力されない let mut reader = File::open(&filename)?; let wordcount = count_words(&mut reader)?; println!("{} {}", wordcount, filename); } Ok(()) }
anyhowがある場合
anyhow::Result<T>
と anyhow::Error
型を使う。
use anyhow::{Result, Context}; use std::env; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; fn count_words<R: Read>(input: R) -> Result<u32> { let reader = BufReader::new(input); let mut wordcount = 0; for line in reader.lines() { for _word in line.context("not line")?.split_whitespace() { wordcount += 1; } } Ok(wordcount) } fn run() -> Result<()> { for filename in env::args().skip(1).collect::<Vec<String>>() { // contextで、anyhow::Errorに変換し、説明を付与できる。 let file = File::open(&filename).context(format!("unable to open {}", filename))?; let wordcount = count_words(&file).context(format!("unable to count words in {}", filename))?; println!("{} {}", wordcount, filename); } Ok(()) } fn main() /*NG main関数ではResult<(), anyhow::Error>を返せない-> Result<()>*/ { if let Err(error) = run() { // Errorを出力する eprintln!("Error: {:?}", error); std::process::exit(0); } }