Option & unwrap

在上一个例子中,我们展示了如何随意地引发程序失败。我们告诉程序如果我们喝了含糖柠檬水就panic。但是,如果我们期待某种饮料却没有收到怎么办?这种情况同样糟糕,因此需要处理!

我们可以像使用柠檬水一样针对空字符串 ("") 进行测试。因为我们使用的是 Rust,所以我们改为让编译器指出没有饮料的情况。

当可能不存在值时,使用std库中的一个名为Option<T>enum。它表现为两种“选项”之一

  • Some(T):找到了一个 T 类型的元素
  • None:未找到任何元素

可以通过 match 显式处理这些情况,也可以使用 unwrap 隐式处理。隐式处理将返回内部元素或 panic

需要注意的是,可以使用 expect 手动自定义 panic,但除此之外,unwrap 提供的结果不如显式处理有意义。在以下示例中,显式处理产生更可控的结果,同时保留了在需要时 panic 的选项。

// The adult has seen it all, and can handle any drink well.
// All drinks are handled explicitly using `match`.
fn give_adult(drink: Option<&str>) {
    // Specify a course of action for each case.
    match drink {
        Some("lemonade") => println!("Yuck! Too sugary."),
        Some(inner)   => println!("{}? How nice.", inner),
        None          => println!("No drink? Oh well."),
    }
}

// Others will `panic` before drinking sugary drinks.
// All drinks are handled implicitly using `unwrap`.
fn drink(drink: Option<&str>) {
    // `unwrap` returns a `panic` when it receives a `None`.
    let inside = drink.unwrap();
    if inside == "lemonade" { panic!("AAAaaaaa!!!!"); }

    println!("I love {}s!!!!!", inside);
}

fn main() {
    let water  = Some("water");
    let lemonade = Some("lemonade");
    let void  = None;

    give_adult(water);
    give_adult(lemonade);
    give_adult(void);

    let coffee = Some("coffee");
    let nothing = None;

    drink(coffee);
    drink(nothing);
}