fn main() {
let input = match user_input::args() {
Ok(input) => input,
Err(e) => {
eprintln!("{}", e);
// return or process::exit(1) ?
}
};
}
If I don't want the program to continue in the error case, should I just return or should I do process::exit(1), or does it matter? In this case I'm building a simple command line tool.
If you only return your program will terminate with the return code 0 which normally indicates a successful execution. If you want to indicate that your program did not run successfully you should use process::exit(1).
A common pattern I use for command line programs is to structure it in the following way
fn _main() -> anyhow::Result<()> {
// Primary application code goes here
let args = parse_args()?; // this is just an example of a function you could have
// …
Ok(())
}
fn main() {
if let Err(e) = _main() {
eprintln!(“Error: {:#?}”, e);
std::process::exit(1)
}
}
anyhow is a popular crate for error handling which makes it easy to not worry about error types in this case. But generally this lets you use ? to early return from the new _main function while also giving a nicer error message and having the application return a non zero value on error.
A good pattern but I'd rather name _main()try_main(). This aligns more with Rust's naming conventions as an _ as prefix indicates unused stuff to the compiler.
Also I want to mention the structopt crate for parsing command line arguments. It just saves a lot of time and pain.
Currently returning a Result from main causes the Debug representation of the error to be printed on Err. @drewkett's example uses the alternative "pretty" Debug representation, and when I write this pattern I tend to use the Display representation (for an error type that implements std::error::Error).
There's been some discussion in the error handling project group about using specialization to print the Display representation in main-returning-Result when the error type implements Error, here's a thread:
Interesting. I actually prefer the Debug impl (alternate flag or no, generally that's only a matter of formatting) because it gives me more actionable information on what to do about it without having to translate it back to the error value.
However, if it was a user-facing app, I can see the value in using Display printing instead.
To be perfectly honest, I didn’t realize that a Result on main did some form of pretty printing on error. I have been doing things the way I have since before you could put Result on main so I guess I never checked what that printed.