首页 / Rust 入门教程 / if let 与 let else

Rust 入门教程

if let 与 let else

本教程共 78 篇 · 第 31 篇 · 更新于 2026-08-08 · 约 11 分钟阅读

RustRust 入门教程if letlet else模式匹配matchwhile letOption

本节目标:用 if let 简写”只关心一种模式”的 match,并用 let else 在模式不匹配时提前退出、同时把匹配到的值绑到外层作用域,让代码更简洁、更扁平。

上一章的 match 很强大,但有时你只对一个模式感兴趣,其他的随便处理一下。硬写完整 match 显得啰嗦。Rust 提供两个简写:if let(只匹配一种情况)和 let else(匹配不到就提前返回)。它们不是新能力,都是 match 的”语法糖”——match 全能干,它们只是把”只关心一个模式”的常见场景写得短一点。

先说一句心里话:初学者常在这俩语法上绕晕,本质是因为它们都是 match 的”偷懒版”。只要记住一个总纲——if let / let else 干的事 match 全能干,它们只是更短。脑子里随时能还原成 match,就不会迷路。

1-1 if let:只关心一个模式

处理 Option 时,如果你只在乎 Some、对 None 草草了事:

let some_number = Some(7);

// 等价于一个只认真处理 Some 的 match
if let Some(x) = some_number {
    println!("拿到值:{x}");
} else {
    println!("没有值");
}

if let Some(x) = some_number 意思是”如果 some_number 能匹配上 Some(x) 这个模式,就把里面的值绑到 x,执行花括号里的内容”。只匹配一种,不必写满整个 match。它背后对应的完整 match 是 match some_number { Some(x) => ..., _ => ... }if let 只是把”一个分支 + 兜底”压缩成更轻的写法。

Note

if letmatch 的语法糖(简写)。凡是 match 只认真处理一个分支、其余用 _ 兜底的情况,都能改写成 if let,读起来更轻。这也是为什么很多 Rust 代码里 if let 出现频率极高——它正好覆盖了”有就处理、没有走默认”这种高频场景。

1-2 if let 不必有 else

如果你只关心命中、不关心没命中,连 else 都可以省:

let some_number = Some(7);
if let Some(x) = some_number {
    println!("值是 {x}");
}
// 没命中就什么都不做,继续往下

这在”有就处理、没有拉倒”的场景里很常见,比如配置项可选、给了才生效。少了 else,代码更轻,但代价是你彻底放弃了”没命中怎么办”的处理——所以只在你真的无所谓时才省略。

1-3 if let 也能匹配枚举变体

不只 Optionif let 对任意枚举的单个变体都好使:

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
}

fn main() {
    let msg = Message::Write(String::from("hi"));
    if let Message::Write(text) = msg {
        println!("收到文本:{text}");
    }
}

只关心 Write 变体、顺手取出里面的 text。若是 QuitMove,就不进这个分支。比写完整 match 省事。注意 if let 这里把变体携带的数据 String 直接绑定到 text 变量,和 match 的解构能力一致。

Tip

解构还能玩得更深:比如 if let Message::Move { x, y } = msg 可以同时取出 xy 两个字段。只要模式能写出来,if let 就能按它解构并绑定变量。所以”只关心一个变体、还要用里面的数据”时,if let 是既短又强的写法。

1-4 while let:循环匹配

顺带一提,还有个 while let,只要模式持续匹配就循环:

fn main() {
    let mut stack = vec![1, 2, 3];
    while let Some(top) = stack.pop() {
        println!("{top}");
    }
}

每次 stack.pop() 返回 Some(值) 就继续循环、取出值;返回 None 就停。这是”边匹配边循环”的便利写法,认识一下即可。它和 if let 同理,只是判断发生在每轮循环开头。日常从队列/栈里不断取元素直到空,用 while let 比手写计数清晰。

1-5 let else:匹配不到就提前退出

let else 解决一个 if let 不方便的场景:你想把匹配到的值绑到外层作用域(让后面代码都能用),同时”匹配不到就立刻返回/退出”。

fn greet(opt: Option<&str>) {
    let name = opt else {
        println!("没人来,撤了");
        return; // 匹配不到(None)时,走这里提前退出
    };
    // 到这里,name 是 &str,在整个函数剩余部分可用
    println!("你好,{name}");
}

let name = opt else { ... } 读作:“试着把 opt 匹配成 Some(name);匹配成功,name 绑到外层供后续用;匹配失败(None),执行 else 块并退出(return/break 等)。“它比 if let 强的地方,就是绑定出的变量能”溢出”到外层作用域,而不是困在 if 块里。

Note

let else 的 else 块必须以发散(diverge)结尾——比如 returnbreakcontinuepanic!,也就是”从这里出去、不再往下”。因为如果不出去,下面代码还在用 name,但 name 根本没绑上,逻辑就矛盾了。编译器强制 else 块必须”走出”当前流程,这正是它安全的地方。

1-6 if let 与 let else 怎么选

  • 只想”命中就做点事、不命中无所谓” → if let(可选带 else)。
  • 想”命中就把值绑到外面一直用,不命中就立刻 return/break 收场” → let else

let else 特别适合函数开头做”前置校验/解包”:拿不到必需的数据就早退,拿到了就继续用,避免函数体被一层层 if let 嵌套撑开。

Tip

一个实用心法:嵌套的 if let 超过两三层,代码会往右缩进成”金字塔”,很难读。把前置校验改成 let else 提前 return,能把它拍平,逻辑清爽很多。这是 Rust 社区推崇的”早退风格(early return)“。

1-7 常见坑:金字塔嵌套

新手最爱写出这样的代码:一上来就是 if let Some(a) = ...,里面又 if let Some(b) = ...,再里面又一层——代码块像金字塔一样从左往右越挤越窄,到最后那几行缩进深得吓人,自己回头都看不懂。

这种”嵌套地狱”的解药就是 let else 早退。把每一层”前置解包”都改成”匹配不到就 return”,主体逻辑就能平铺在左边同一级缩进上。读起来是”先排除所有意外,再走正常流程”,比”层层包裹”清晰十倍。

// 早退风格:主体逻辑平铺在左边
fn show_user(id: Option<u32>) {
    let uid = id else {
        println!("缺少用户 id");
        return;
    };
    println!("处理用户 {uid}");
}

1-8 if let 与 match 的取舍

if letmatch 怎么取舍?一句话:只关心”一个模式、且其余情况不值得单独处理”时用 if let;“必须处理每一种可能”时用 match。比如处理 Option,如果 None 时真的”什么都不用做”,if let Some(x) = opt { ... } 就够清爽;如果 None 也要有明确动作(报错、返回),用 matchSomeNone 都写出来,语义更完整、也不会漏。

Tip

if let 里开始堆 else if let ... else if let ...,说明你在手动模拟 match,这时换成 match 通常更清楚,还能强制穷尽。工具没有绝对好坏,看”分支数量”和”是否需要穷尽保证”来选。需要穷尽保证时,match 是更稳的选择,因为编译器会逼你把每个变体都写上。

1-9 小结

if let 是”只关心一个模式”的 match 简写;let else 在匹配失败时提前退出、成功则把值绑到外层。它们和 match 互为补充:穷尽用 match,单一模式用 if let,要早退解包用 let else。

回过头看,这三个工具是一体的:match 是完整的多分支穷尽匹配;if let 是”只处理一个分支、其余默认”的精简版;let else 是”匹配就继续、不匹配就早退”的解包版。初学者不必强求第一眼就用最简洁的写法——先把 match 写对、写全,再按需简化成 if let / let else,是更稳妥的学习路径。下一章进入”包、crate 与模块系统”,学习如何把代码按功能组织成大项目。