模式匹配 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 config_max {
Some (max) => println! ("最大值: {}" , max),
_ => (),
}
if let Some (max) = config_max {
println! ("最大值: {}" , max);
}
if let Some (max) = config_max {
println! ("最大值: {}" , max);
} else {
println! ("没有设置最大值" );
}
}
复制
while let
fn main () {
let mut stack = vec! [1 , 2 , 3 , 4 , 5 ];
while let Some (top) = stack.pop () {
println! ("{}" , top);
}
}
复制
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 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 ),
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! ("有值" ),
None => println! ("无" ),
}
复制
小结
语法 用途 match x { ... }穷尽匹配 _通配符 |多模式 ..=范围模式 if let只关心一个分支 while let循环直到不匹配 let else不匹配则提前返回