模式匹配 match
学习目标
- 掌握
match表达式的完整用法 - 理解穷尽性(exhaustive)
- 掌握各种模式语法
- 掌握
if let和while let
核心概念
基本 match
fn main() {
let number = 3;
match number {
1 => println!("一"),
2 => println!("二"),
3 => println!("三"),
_ => println!("其他"), // _ 是通配符,匹配所有
}
}
匹配枚举
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: &Coin) -> u32 {
match coin {
Coin::Penny => {
println!("幸运便士!");
1
}
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
绑定值
enum Shape {
Circle(f64),
Rectangle(f64, f64),
}
fn describe(shape: &Shape) -> String {
match shape {
Shape::Circle(r) => format!("圆形,半径 {}", r),
Shape::Rectangle(w, h) => format!("矩形,{}×{}", w, h),
}
}
匹配守卫(match guard)
fn main() {
let x = 4;
match x {
n if n < 0 => println!("负数"),
n if n == 0 => println!("零"),
n if n % 2 == 0 => println!("{} 是偶数", n),
n => println!("{} 是奇数", n),
}
}
多模式
fn main() {
let x = 1;
match x {
1 | 2 => println!("一或二"), // | 表示或
3..=9 => println!("三到九"), // 范围
_ => println!("其他"),
}
}
fn main() {
let c = 'z';
match c {
'a'..='j' => println!("前半"),
'k'..='z' => println!("后半"),
_ => println!("其他"),
}
}
解构结构体
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 7 };
match p {
Point { x, y: 0 } => println!("在 x 轴上: {}", x),
Point { x: 0, y } => println!("在 y 轴上: {}", y),
Point { x, y } => println!("({},{})", x, y),
}
}
解构嵌套
enum Color {
Rgb(u8, u8, u8),
Hsl(u16, u8, u8),
}
enum Message {
Quit,
Color(Color),
}
fn main() {
let msg = Message::Color(Color::Rgb(255, 128, 0));
match msg {
Message::Color(Color::Rgb(r, g, b)) => {
println!("RGB({}, {}, {})", r, g, b);
}
Message::Color(Color::Hsl(h, s, l)) => {
println!("HSL({}, {}, {})", h, s, l);
}
Message::Quit => println!("退出"),
}
}
忽略值
fn main() {
let point = (1, 2, 3);
match point {
(0, _, _) => println!("x 是 0"),
(_, 0, _) => println!("y 是 0"),
(_, _, 0) => println!("z 是 0"),
_ => println!("没有零"),
}
// 忽略剩余字段
let (_, y, _) = point;
println!("y = {}", y);
}
if let(简写)
fn main() {
let config_max: Option<u8> = Some(3);
// 完整 match
match config_max {
Some(max) => println!("最大值: {}", max),
_ => (), // 不关心 None
}
// if let 简写
if let Some(max) = config_max {
println!("最大值: {}", max);
}
// if let + else
if let Some(max) = config_max {
println!("最大值: {}", max);
} else {
println!("没有设置最大值");
}
}
while let
fn main() {
let mut stack = vec![1, 2, 3, 4, 5];
// pop 返回 Option<T>
while let Some(top) = stack.pop() {
println!("{}", top);
}
// 输出: 5, 4, 3, 2, 1
}
let else(Rust 1.65+)
fn get_count(item: &str) -> Option<u32> {
match item {
"apple" => Some(5),
"banana" => Some(3),
_ => None,
}
}
fn main() {
let item = "apple";
// let else:不匹配时提前返回
let Some(count) = get_count(item) else {
println!("未知物品");
return;
};
println!("数量: {}", count);
}
实践练习
练习 1:扑克牌
#[derive(Debug)]
enum Suit {
Hearts,
Diamonds,
Clubs,
Spades,
}
#[derive(Debug)]
enum Rank {
Ace,
Number(u8), // 2-10
Jack,
Queen,
King,
}
fn describe_card(suit: &Suit, rank: &Rank) -> String {
let suit_str = match suit {
Suit::Hearts => "♥",
Suit::Diamonds => "♦",
Suit::Clubs => "♣",
Suit::Spades => "♠",
};
let rank_str = match rank {
Rank::Ace => String::from("A"),
Rank::Number(n) => n.to_string(),
Rank::Jack => String::from("J"),
Rank::Queen => String::from("Q"),
Rank::King => String::from("K"),
};
format!("{}{}", suit_str, rank_str)
}
fn main() {
let hand = [
(Suit::Hearts, Rank::Ace),
(Suit::Spades, Rank::King),
(Suit::Diamonds, Rank::Number(7)),
];
for (suit, rank) in &hand {
println!("{}", describe_card(suit, rank));
}
}
练习 2:简单计算器
enum Op {
Add,
Sub,
Mul,
Div,
}
fn calculate(a: f64, op: &Op, b: f64) -> Option<f64> {
match op {
Op::Add => Some(a + b),
Op::Sub => Some(a - b),
Op::Mul => Some(a * b),
Op::Div => {
if b == 0.0 { None } else { Some(a / b) }
}
}
}
fn main() {
let ops = [Op::Add, Op::Sub, Op::Mul, Op::Div];
for op in &ops {
match calculate(10.0, op, 3.0) {
Some(result) => println!("结果: {}", result),
None => println!("错误: 除以零"),
}
}
}
常见错误
1. 非穷尽匹配
let x: i32 = 5;
match x {
1 => println!("一"),
2 => println!("二"),
// ❌ 缺少 _ 分支,编译器要求穷尽
}
2. 忘记绑定变量
let some_value = Some(5);
match some_value {
Some(_) => println!("有值"), // _ 忽略了值
// 想用值的话要 Some(x)
None => println!("无"),
}
小结
| 语法 | 用途 |
|---|---|
match x { ... } | 穷尽匹配 |
_ | 通配符 |
| | 多模式 |
..= | 范围模式 |
if let | 只关心一个分支 |
while let | 循环直到不匹配 |
let else | 不匹配则提前返回 |
练习编辑器
rust
Loading...