Option & unwrap

在上个例子中,我们显示出我们能够任意引入程序失败(program failure)。当公主收到蛇这件不合适的礼物时,我们就告诉程序产生 panic。但是,如果公主期待一件礼物却没收到呢?这同样是一件糟糕的事情,所以我们要想办法来解决这个问题!

我们可以检查空字符串(""),就像处理蛇那样的方式。既然我们使用了 Rust,那我们就让编译器指出没有礼物的情况。

在标准库(std)中有个叫做 Option<T> (option 中文意思是“选项”)的枚举类型,用于变量可能不存在的情景(原文:An enum called Option<T> in the std library is used when absence is a possibility. )。它表现为以下两个 “options”(选项)中的其中一个:

  • Some(T):找到一个属于 T 类型的元素
  • None:找不到相应元素

这些选项可以通过 match 显式地处理,或使用 unwrap 隐式地处理。隐式处理会返回内部元素或 panic

请注意,手动使用 expect 方法自定义 panic 是可能的,而 unwrap 相比显式处理则留下不太有意义的输出。在下面例子中,显式处理得到更具可控性的结果,同时若需要的话,可将选项保留为 panic。(本段原文:Note that it’s possible to manually customize panic with expect, but unwrap otherwise leaves us with a less
meaningful output than explicit handling. In the following example, explicit handling yields a more controlled result while retaining the option to panic if desired. )

  1. // 平民(commoner)已经见过所有东西,并能妥善处理好各种情况。
  2. // 所有礼物都通过手动使用 `match` 来处理。
  3. fn give_commoner(gift: Option<&str>) {
  4. // 指出每种情况下的做法。
  5. match gift {
  6. Some("snake") => println!("Yuck! I'm throwing that snake in a fire."),
  7. Some(inner) => println!("{}? How nice.", inner),
  8. None => println!("No gift? Oh well."),
  9. }
  10. }
  11. // 我们受保护的公主见到蛇将会 `panic`(恐慌)。
  12. fn give_princess(gift: Option<&str>) {
  13. // 使用 `unwrap`,当接收到 `None` 时返回一个 `panic`。
  14. let inside = gift.unwrap();
  15. if inside == "snake" { panic!("AAAaaaaa!!!!"); }
  16. println!("I love {}s!!!!!", inside);
  17. }
  18. fn main() {
  19. let food = Some("chicken");
  20. let snake = Some("snake");
  21. let void = None;
  22. give_commoner(food);
  23. give_commoner(snake);
  24. give_commoner(void);
  25. let bird = Some("robin");
  26. let nothing = None;
  27. give_princess(bird);
  28. give_princess(nothing);
  29. }