模式匹配
match
enum Direction { Left, Right, Top(u8), Bottom } fn main() { fn match_direction(direction: Direction) -> Option<u8> { match direction { Direction::Top(x) => { println!("top"); Some(x) // 可以有返回值 }, // 使用|匹配多种情况 Direction::Left | Direction::Right => { println!("left or right"); Some(20) }, _ => { // 剩余情况 println!("other"); None } } } println!("Left: {:?}", match_direction(Direction::Left)); println!("Right: {:?}", match_direction(Direction::Right)); println!("Top: {:?}", match_direction(Direction::Top(99))); println!("Bottom: {:?}", match_direction(Direction::Bottom)); }
if let
enum Direction { Left, Right, Top(u8), Bottom } fn main() { fn is_direction_top(d: Direction) -> u8 { if let Direction::Top(x) = d { println!("{} is top", x); x } else { 0 } } println!("is_direction_top: {}", is_direction_top(Direction::Bottom)); println!("is_direction_top: {}", is_direction_top(Direction::Top(20))); }
match! 宏
enum Direction { Left, Right, Top(u8), Bottom } fn main() { let card1 = Direction::Top(1); // 我们不能直接用 == 判断枚举是否相等 // let r = card1 == Direction::Top(1); println!("{}", matches!(card1, Direction::Top(1))); // true println!("{}", matches!(card1, Direction::Top(2))); // false println!("{}", matches!(card1, Direction::Top(_))); // true // 表示忽略携带的值 println!("{}", matches!(card1, Direction::Bottom)); // false }
let else
可以理解为反向匹配 匹配不满足的情况 忽略所有满足的情况
enum Direction { Left, Right, Top(u8), Bottom } fn main() { fn do_not(d: Direction) -> Option<bool> { let Direction::Top(x) = d else { // 这里访问不到x return Some(true); // 必须为发散模式 }; println!("在这里可以访问到x: {}", x); Some(false) } println!("Top: {:?}", do_not(Direction::Top(1))); println!("Bottom: {:?}", do_not(Direction::Bottom)); }
while let
fn main() { let arr = [10, 20, 30, 40, 50]; let mut index = 0; // 循环匹配 直至匹配不中 while let Some(n) = arr.get(index) { index += 1; println!("{}", n); } }
匹配守卫
fn main() { fn match_x(x: Option<i32>) { match x { Some(v) if v > 0 => println!("x 大于0: {}", v), // 当if后的条件为true时才进入 Some(v) => println!("x 小于等于0:{}", v), None => println!("none") } } match_x(Some(5)); match_x(Some(0)); }
@绑定
fn main() { fn match_x(x: Option<i32>) { match x { Some(v @ 5..10 ) => println!("5-10内: {}", v), Some(v) => println!("不在5-10之内: {}", v), None => () } } match_x(Some(12)); match_x(Some(6)); #[derive(Debug)] enum Action { Move {x: i32, y: i32} } fn match_struct(action: Action) { match action { Action::Move {x: a, y : b @ 1..10} => { println!("action move 在 1到10: {}", b); } ac @ Action::Move {x, y: b @ 10..20} => { println!("action move 10到20: {}, {:?}", b, ac); // println!("action: {:?}", action); // 这里访问不了action了因为他的所有权被移动到ac上了 } ref ac @ Action::Move {x: a, y: b} => { println!("在这之外: {:?} {:?}", ac, action); println!("action: {:?}", action); // 这里还能继续访问action。 因为ac只是对action引用 } } } let action1 = Action::Move {x: 10, y: 6}; let action2 = Action::Move {x: 10, y: 15}; let action3 = Action::Move {x: 100, y: 100}; println!("action1: {:?}, action2: {:?}, action3: {:?}", action1, action2, action3); match_struct(action1); match_struct(action2); match_struct(action3); // 搭配guard #[derive(Debug)] struct Member { name: String, age: u8, is_vip: bool } // 用来配合 guard 条件 fn match_member(member: &Member) { match member { m @ Member { age: 18..60, .. } if m.is_vip => { println!("{}是18岁以上的vip用户", m.name); } _ => { println!("ignore") } } } let m1 = Member { name: "cxk".to_string(), age: 19, is_vip: true }; match_member(&m1); println!("m1: {:?}", m1); }