模式匹配 在 Rust 中允许根据结构分解值,使用 match、if let、while let 语句分析并处理复杂类型。解构(拆分成部分)对于处理元组、结构体、枚举甚至引用都很方便。
使用枚举的示例:
enum Message { Quit, ChangeColor(i32, i32, i32), Write(String), } let m = Message::ChangeColor(255, 0, 0); match m { Message::Quit => println!("Quit!"), Message::ChangeColor(r, g, b) => println!("Color: {} {} {}", r, g, b), Message::Write(text) => println!("Text: {}", text), }
解构结构体的示例:
struct Point { x: i32, y: i32 } let p = Point { x: 10, y: 20 }; let Point { x, y } = p;
细节:
ref 和 ref mut 可以在解构时获得引用。@ 可以 "重新命名" 模式的一部分。if guard)。&SomeType)时,重要的是要记住所有权和借用。是否可以总是使用 "_"(下划线)来忽略模式的部分,避免编译器警告?
并不总是可以。下划线确实会跳过值,但如果在枚举的模式匹配中未处理所有选项而使用 "_" 作为 catch-all,您可能会在未来扩展枚举时遗漏新选项的处理。最好总是明确列出重要选项,以便编译器对未处理的情况发出警告!
match result { Ok(val) => ..., Err(err) => ..., //_ => ... // 不建议用于枚举! }
故事
在 IoT 应用中,由于在模式匹配时添加新枚举选项而使用了 catch-all "_",设备停止响应。错误在部署之前未被发现。此后,关键的枚举总是通过明确列举选项进行处理。
故事
对于具有嵌套元组的复杂结构,忘记添加递归字段的解构语法,代码意外克隆了大型对象,导致性能下降。
故事
在流之间传递消息的一个功能中,使用了通过 if-let 的解构,但忽略了枚举中的稀有选项。当新的业务逻辑出现时,消息会直接丢失。之后团队制定了规则——每个 match 表达式必须是全面的,避免 catch-all。