TODO

Step6

修复错误处理

这一节稍有一点复杂,但也非常重要,对以后写程序或看别人的程序都非常有用,主要就是对 Result<Config, Err> 这样的结构的理解。

这一节分为三个小步骤。



小步骤 1: 改进的 panic

现在如果运行 cargo run ,后面不带参数,会出现 panic 错误,thread 'main' panicked at 'index out of bounds: ...', 这是一个很笼统的错误信息,修改产生一个手动的 panic 来提供更有意义的错误信息提示。



小步骤 1 answer
// --snip--
fn new(args: &[String]) -> Config {
    if args.len() < 3 {
        panic!("not enough arguments");
    }
    // --snip--



小步骤 2: 从 new 中返回 Result 而不是调用 panic!

让 new 函数返回 Result<Config, &'static str> 而不是 Config, 将 panic 改写为 return Err()

( 现在如果运行 cargo run ,会出现程序错误,因为还没有在 main() 里面处理返回的错误, 这将在小步骤3里面处理。)



小步骤 2 answer
impl Config {
    fn new(args: &[String]) -> Result<Config, &'static str> {
        if args.len() < 3 {
            return Err("not enough arguments");
        }

        let query = args[1].clone();
        let filename = args[2].clone();

        Ok(Config { query, filename })
    }
}



小步骤 3: 在 main() 中处理 Config::new 返回的错误

使用 unwrap_or_else(|err| {}) 形式来处理返回的错误信息

导入 std::process , 当 Config::new 返回错误的时候说明参数解析出现错误,程序没必要再运行下去,使用 process.exit(1) 退出程序。

现在运行 cargo run ,看看程序错误提示



小步骤 3 answer
use std::process;

fn main() {
    let args: Vec<String> = env::args().collect();

    let config = Config::new(&args).unwrap_or_else(|err| {
        println!("Problem parsing arguments: {}", err);
        process::exit(1);
    });

    // --snip--