模式匹配(Pattern Matching)#

Rust 的 模式匹配 是一套強大的機制,能夠解構並檢查各種資料結構。 模式可以用在 matchif letwhile letforlet 和函數參數等地方。


1. 字面值模式#

直接比對具體的值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fn main() {
    let x = 3;

    match x {
        1 => println!("一"),
        2 => println!("二"),
        3 => println!("三"),
        _ => println!("其他"),
    }
}

2. 綁定變數#

match 中將匹配到的值綁定到一個變數:

1
2
3
4
5
6
7
fn main() {
    let n = 42;

    match n {
        x => println!("匹配到 {x}"),
    }
}

3. 多個模式(|)#

| 可以在同一個分支匹配多個模式:

1
2
3
4
5
6
7
8
9
fn main() {
    let x = 2;

    match x {
        1 | 2 => println!("一或二"),
        3 | 4 => println!("三或四"),
        _     => println!("其他"),
    }
}

4. 範圍模式(..=)#

使用 ..= 匹配一個範圍內的值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
fn classify(score: u32) -> &'static str {
    match score {
        90..=100 => "優",
        80..=89  => "良",
        70..=79  => "中",
        60..=69  => "及格",
        _        => "不及格",
    }
}

fn main() {
    println!("{}", classify(85)); // 良
    println!("{}", classify(55)); // 不及格
}

5. 解構結構體#

match 可以解構結構體的欄位:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 3, y: -5 };

    match p {
        Point { x: 0, y } => println!("在 Y 軸上,y = {y}"),
        Point { x, y: 0 } => println!("在 X 軸上,x = {x}"),
        Point { x, y }    => println!("座標 ({x}, {y})"),
    }
}

6. 解構枚舉#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    Color(u8, u8, u8),
}

fn process(msg: Message) {
    match msg {
        Message::Quit                    => println!("離開"),
        Message::Move { x, y }          => println!("移動到 ({x}, {y})"),
        Message::Write(text)             => println!("寫入:{text}"),
        Message::Color(r, g, b)         => println!("顏色 RGB({r}, {g}, {b})"),
    }
}

7. 解構元組#

1
2
3
4
5
6
7
8
9
fn main() {
    let pair = (0, -1);

    match pair {
        (0, y) => println!("x 是零,y = {y}"),
        (x, 0) => println!("y 是零,x = {x}"),
        (x, y) => println!("({x}, {y})"),
    }
}

8. 守衛條件(Match Guard)#

match 分支後加上 if 條件,只有條件成立時才匹配:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fn main() {
    let pair = (2, -3);

    match pair {
        (x, y) if x == y     => println!("相等"),
        (x, y) if x + y == 0 => println!("互為相反數"),
        (x, _) if x % 2 == 0 => println!("x 是偶數"),
        _                     => println!("其他"),
    }
}

9. @ 綁定#

@ 讓你在匹配範圍模式時,同時把匹配到的值綁定到變數:

1
2
3
4
5
6
7
8
9
fn main() {
    let n = 15;

    match n {
        x @ 1..=10  => println!("{x} 在 1 到 10 之間"),
        x @ 11..=20 => println!("{x} 在 11 到 20 之間"),
        x           => println!("{x} 超出範圍"),
    }
}

10. let 解構#

let 本身也支援模式,可以直接解構元組或結構體:

1
2
3
4
5
6
7
8
fn main() {
    let (a, b, c) = (1, 2, 3);
    println!("{a}, {b}, {c}");

    struct Point { x: i32, y: i32 }
    let Point { x, y } = Point { x: 10, y: 20 };
    println!("{x}, {y}");
}

11. 函數參數解構#

函數參數也可以直接解構:

1
2
3
4
5
6
7
8
fn print_point(&(x, y): &(i32, i32)) {
    println!("({x}, {y})");
}

fn main() {
    let p = (3, 5);
    print_point(&p);
}

Reference#

https://doc.rust-lang.org/book/ch18-00-patterns.html