Rust 模式(Pattern)

匹配字面量 #

let x = 1;
match x {
    1 => println!("one") ,
    2 => println!("two"),
    3 => println!("three") ,
    _ => println!("anything"),
}

匹配变量 #

let x = Some(5);
match x {
    Some(50) => println!("Got 50"),
    Some(y) => println!("Got {:?}", y),
    _ => println!("Got something else {:?}", x),
}

一个分支多个模式 #

let x = 1;
match x {
    1 | 2 => println!("one or two"),
    3 => println!("three"),
    _ => println!("anything"),
}

用..=匹配范围 #

目前只支持..=

let x = 5;
 
match x {
    1..=5 => println!("one through five"),
    _ => println!("something else"),
}
 
let x = 'c';
 
match x {
    'a'..='j' => println!("early ASCII letter"),
    'k'..='z' => println!("late ASCII letter"),
    _ => println!("something else"),
}

分解结构体(Destructing Structs) #

struct Point {
    x: i32,
    y: i32,
}
 
fn main() {
    let p = Point { x: 0, y: 7 };
 
    let Point { x: a, y: b } = p;
    assert_eq!(0, a);
    assert_eq!(7, b);
}

当变量名称与 field 名称相同时可以简写:

struct Point {
    x: i32,
    y: i32,
}
 
fn main() {
    let p = Point { x: 0, y: 7 };
 
    let Point { x, y } = p;
    assert_eq!(0, x);
    assert_eq!(7, y);
}

匹配部分:

struct Point {
    x: i32,
    y: i32,
}
 
fn main() {
    let p = Point { x: 0, y: 7 };
 
    match p {
        Point { x, y: 0 } => println!("On the x axis at {}", x),
        Point { x: 0, y } => println!("On the y axis at {}", y),
        Point { x, y } => println!("On neither axis: ({}, {})", x, y),
    }
}

分解 Enums #

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
 
fn main() {
    let msg = Message::ChangeColor(0, 160, 255);
 
    match msg {
        Message::Quit => {
            println!("The Quit variant has no data to destructure.")
        }
        Message::Move { x, y } => {
            println!(
                "Move in the x direction {} and in the y direction {}",
                x, y
            );
        }
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => println!(
            "Change the color to red {}, green {}, and blue {}",
            r, g, b
        ),
    }
}

分解嵌套的结构体或者 Enums #

enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}
 
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(Color),
}
 
fn main() {
    let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
 
    match msg {
        Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
            "Change the color to red {}, green {}, and blue {}",
            r, g, b
        ),
        Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
            "Change the color to hue {}, saturation {}, and value {}",
            h, s, v
        ),
        _ => (),
    }
}

分解结构体和元组 #

fn main() {
    struct Point {
        x: i32,
        y: i32,
    }
 
    let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });
}

忽略模式中的值 #

_忽略整个值:

fn foo(_: i32, y: i32) {
    println!("This code only uses the y parameter: {}", y);
}
 
fn main() {
    foo(3, 4);
}

用嵌套的_忽略值的部分:

fn main() {
    let mut setting_value = Some(5);
    let new_setting_value = Some(10);
 
    match (setting_value, new_setting_value) {
        (Some(_), Some(_)) => {
            println!("Can't overwrite an existing customized value");
        }
        _ => {
            setting_value = new_setting_value;
        }
    }
 
    println!("setting is {:?}", setting_value);
}

忽略元组的部分值:

fn main() {
    let numbers = (2, 4, 8, 16, 32);
 
    match numbers {
        (first, _, third, _, fifth) => {
            println!("Some numbers: {}, {}, {}", first, third, fifth)
        }
    }
}

忽略剩余部分:

fn main() {
    struct Point {
        x: i32,
        y: i32,
        z: i32,
    }
 
    let origin = Point { x: 0, y: 0, z: 0 };
 
    match origin {
        Point { x, .. } => println!("x is {}", x),
    }
}

匹配第一个和最后一个:

fn main() {
    let numbers = (2, 4, 8, 16, 32);
 
    match numbers {
        (first, .., last) => {
            println!("Some numbers: {}, {}", first, last);
        }
    }
}

利用 Match Guards 实现更多的条件 #

fn main() {
    let num = Some(4);
 
    match num {
        Some(x) if x % 2 == 0 => println!("The number {} is even", x),
        Some(x) => println!("The number {} is odd", x),
        None => (),
    }
}

多模式:

fn main() {
    let x = 4;
    let y = false;
 
    match x {
        4 | 5 | 6 if y => println!("yes"), // 等价于 (4 | 5 | 6) if y =>
        _ => println!("no"),
    }
}

@绑定 #

@允许我们在创建变量的同时测试变量的值

fn main() {
    enum Message {
        Hello { id: i32 },
    }
 
    let msg = Message::Hello { id: 5 };
 
    match msg {
        Message::Hello {
            id: id_variable @ 3..=7,
        } => println!("Found an id in range: {}", id_variable),
        Message::Hello { id: 10..=12 } => {
            println!("Found an id in another range")
        }
        Message::Hello { id } => println!("Found some other id: {}", id),
    }
}

Reference: Pattern Syntax