解构

与元组一样,结构体和枚举也可以通过匹配方式进行解构:

结构体

  1. struct Foo {
  2. x: (u32, u32),
  3. y: u32,
  4. }
  5. #[rustfmt::skip]
  6. fn main() {
  7. let foo = Foo { x: (1, 2), y: 3 };
  8. match foo {
  9. Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"),
  10. Foo { y: 2, x: i } => println!("y = 2, x = {i:?}"),
  11. Foo { y, .. } => println!("y = {y}, other fields were ignored"),
  12. }
  13. }

枚举

模式还可用于将变量绑定到值的某些部分。这是您检查类型结构的方式。我们先从简单的“enum”类型开始:

  1. enum Result {
  2. Ok(i32),
  3. Err(String),
  4. }
  5. fn divide_in_two(n: i32) -> Result {
  6. if n % 2 == 0 {
  7. Result::Ok(n / 2)
  8. } else {
  9. Result::Err(format!("cannot divide {n} into two equal parts"))
  10. }
  11. }
  12. fn main() {
  13. let n = 100;
  14. match divide_in_two(n) {
  15. Result::Ok(half) => println!("{n} divided in two is {half}"),
  16. Result::Err(msg) => println!("sorry, an error happened: {msg}"),
  17. }
  18. }

在这里,我们使用了分支来解构“Result”值。在第一个分支中,“half”被绑定到“Ok”变体中的值。在第二个分支中,“msg”被绑定到错误消息。

This slide should take about 8 minutes.

结构体

  • 更改“foo”中的字面量值以与其他模式相匹配。
  • 向“Foo”添加一个新字段,并根据需要更改模式。
  • 捕获和常量表达式之间的区别可能很难发现。尝试将第二个分支中的“2”更改为一个变量,可以看到它几乎无法运作了。将它更改为“const”,可以看到它又正常运作了。

枚举

关键点:

  • “if”/“else”表达式将返回一个枚举,该枚举之后会使用“match”进行解封装。
  • 您可以尝试在枚举定义中添加第三个变体,并在运行代码时显示错误。指出代码现在有哪些地方还不详尽,并说明编译器会如何尝试给予提示。
  • The values in the enum variants can only be accessed after being pattern matched.
  • Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are handled.
  • Save the result of divide_in_two in the result variable and match it in a loop. That won’t compile because msg is consumed when matched. To fix it, match &result instead of result. That will make msg a reference so it won’t be consumed. This “match ergonomics” appeared in Rust 2018. If you want to support older Rust, replace msg with ref msg in the pattern.