Visualizzare messaggi di errore descrittivi
A questo punto, se si prova a leggere un file journal che non esiste, il programma va in panico con l'output seguente:
$ cargo run -- done 2
thread 'main' panicked at 'Failed to perform action: Os { code: 2, kind: NotFound, message: "No such file or directory" }'
Questo errore è un po' dettagliato per gli utenti, quindi è consigliabile renderlo più comprensibile. È possibile scrivere molto codice per gestire questa attività, ma esiste un crate perfetto per visualizzare errori utili e semplici per gli utenti. Lo strumento è chiamato anyhow
.
La logica alla base del crate anyhow
è che fornisce un tipo di errore specifico. Questo tipo ha proprietà di riformattazione che possono essere facilmente convertite da altri errori, ad esempio std::io::Error
. È facile aggiungere anyhow
al progetto. È sufficiente inserirlo come tipo restituito della funzione main
.
Prima di tutto, dichiararlo nel file Cargo.toml
:
[dependencies]
anyhow = "1.0" # <--- Add `anyhow` to our project dependencies.
home = "0.5"
serde_json = "1.0"
structopt = "0.3"
[dependencies.chrono]
features = ["serde"]
version = "0.4"
[dependencies.serde]
features = ["derive"]
version = "1.0"
Aggiornare ora la firma della funzione main
in modo che restituisca il tipo anyhow::Result<()>
:
use anyhow::anyhow;
use std::path::PathBuf;
use structopt::StructOpt;
mod cli;
mod tasks;
use cli::{Action::*, CommandLineArgs};
use tasks::Task;
fn find_default_journal_file() -> Option<PathBuf> {
home::home_dir().map(|mut path| {
path.push(".rust-journal.json");
path
})
}
fn main() -> anyhow::Result<()> {
let CommandLineArgs {
action,
journal_file,
} = CommandLineArgs::from_args();
let journal_file = journal_file
.or_else(find_default_journal_file)
.ok_or(anyhow!("Failed to find journal file."))?;
match action {
Add { text } => tasks::add_task(journal_file, Task::new(text)),
List => tasks::list_tasks(journal_file),
Done { position } => tasks::complete_task(journal_file, position),
}?;
Ok(())
}
Poiché la maggior parte dei tipi di errore può essere convertita in anyhow::Error
, è possibile usare la sintassi ?
per rimuovere le chiamate a expect
dal codice. Si noti anche che si sta usando la macro anyhow!
per produrre immediatamente un elemento anyhow::Error
contenente il messaggio di errore specificato.
A questo punto, ogni messaggio di panico causato da un errore di I/O restituito dal programma verrà visualizzato agli utenti come segue:
$ cargo run -- -j missing-journal done 2
Error: No such file or directory (os error 2)
Si tratta di un notevole miglioramento per poche righe di codice aggiuntive.