news 2026/9/10 11:18:57

Rust 控制流基础:Comprehensive Rust 中的 `if` 表达式详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rust 控制流基础:Comprehensive Rust 中的 `if` 表达式详解

Rust 控制流基础:Comprehensive Rust 中的if表达式详解

【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust

if是 Rust 中最基础的控制流构造,但它与 C、Java 等语言最大的不同在于:Rust 的if是一个表达式(expression)而非语句(statement),它可以产生值、可以出现在let绑定右侧,还能与类型系统进行强制的分支类型统一检查。本文以 Google Android 团队维护的 Comprehensive Rust 课程中ifexpressions 一节为核心,结合课程源码与配套练习,系统讲解if表达式的语法、分支类型一致性、尾表达式求值规则,以及它在实际代码(如 Collatz 序列练习)中的惯用写法。

一、课程定位:if在 Comprehensive Rust 中的位置

if表达式属于课程 "Day 1: Morning" 的Control Flow Basics章节,位于 控制流基础总览 之下。根据课程目录 SUMMARY.md 的编排顺序,本节的前置知识是 Blocks and Scopes(块与作用域),后续则衔接 match 表达式、循环(while/loop/for) 与 break 和 continue。

该节标注的授课时长为4 分钟,属于快速推进的入门内容。课程意图非常明确:先让学员掌握if的“类语句”用法,再揭示其“表达式”本质,为后面理解match、函数尾表达式返回、以及一切“块即表达式”的 Rust 核心哲学铺路。

Control Flow Basics ├── Blocks and Scopes ← 块与作用域(表达式基础) ├── if Expressions ← 本文主题 ├── match Expressions ├── Loops(while / loop / for) ├── break 和 continue(含标签) ├── Functions └── Macros

二、作为“语句”使用的if:与其他语言的相似之处

Rust 的if在常规场景下与其他语言的if语句用法完全一致:根据条件执行不同分支。

fn main() { let x = 10; if x == 0 { println!("zero!"); } else if x < 100 { println!("biggish"); } else { println!("huge"); } }

运行结果是打印biggish。这里有几个值得注意的语法细节:

  • 条件不需要括号if x == 0而非if (x == 0),圆括号是可选的(作为表达式的一部分时括号也经常省略);
  • 分支必须用花括号包裹:即使分支体只有一行,{}也不可省略。这与其他语言(如 Python 的缩进、Go 的强制花括号)风格不同,避免了悬挂else(dangling else)问题;
  • else if:Rust 没有独立的elseif关键字,else if是多个if表达式的嵌套组合,可任意串联。

课程原文强调“You useifexpressions exactly likeifstatements in other languages”,即这一层用法对任何有编程经验的开发者都是零门槛的。

三、核心特性:if是表达式,可以产生值

if真正区别于“语句式”语言的地方在于:每个分支块的最后一个表达式会成为整个if表达式的值

fn main() { let x = 10; let size = if x < 20 { "small" } else { "large" }; println!("number size: {}", size); }

输出:

number size: small

这里if x < 20 { "small" } else { "large" }整体被求值为"small",并绑定给变量size。变量size的类型是&str,由两个分支共同决定。

这种写法的价值在于:

  1. 消除可变绑定:不需要先let mut size = "large";再在分支里赋值,变量声明即完成初始化,天然符合 Rust 的所有权与不可变优先风格;
  2. 表达式嵌套if可以出现在任何期望值的位置——let绑定、函数参数、return语句、甚至另一个if的分支里;
  3. 配合尾表达式:函数体最后一个if表达式可以直接作为返回值(见下文第五节)。

四、分支类型必须一致:编译器的强制约束

因为if是表达式且“必须具有某个特定类型”(must have a particular type),两个分支块必须具有相同的类型。这是 Rust 类型系统给出的强保证。

课程在隐藏备注(<details>)中提供了一个很好的课堂实验:在第二个示例中给"small"加上分号,即:

let size = if x < 20 { "small"; } else { "large" };

这样"small";所在分支的块尾表达式变成了单元类型()(因为分号会吞掉表达式值),而else分支仍然是&str,两分支类型不一致,编译器会直接报错。这也是理解 块与作用域 中“如果最后一个表达式以;结尾,则块的值为()”这一规则的关键应用。

同理,if表达式作为表达式使用时必须遵守普通表达式语法:当它出现在let语句中时,整个let语句同样要以;结束。课程建议删除println!前的;观察编译错误,这正是让学员体会“let绑定语句必须以分号收尾”这一句法规则的实战演练。

// 正确写法:let 语句以分号结束 let size = if x < 20 { "small" } else { "large" }; // ← 这行末尾的分号不能少 // 错误写法:缺少分号会导致语法错误 // let size = if x < 20 { "small" } else { "large" } println!("number size: {}", size);

分支一致性的意义

  • 类型安全if的结果可以被安全地赋给任意类型标注变量,编译器在编译期就能发现分支类型分叉的 bug;
  • 可穷举性:配合match的穷尽性检查(match 表达式),Rust 保证每个表达式路径都有确定的值,没有“隐式返回 null”的暗坑。

五、if表达式的惯用场景:函数尾返回与循环体内赋值

5.1 函数体的尾表达式返回

Rust 函数体中“最后一个表达式成为返回值”。因此if表达式可以直接充当函数返回值,这是课程 函数 一节展示的写法:

fn gcd(a: u32, b: u32) -> u32 { if b > 0 { gcd(b, a % b) } else { a } }

这个递归求最大公约数的函数,用单个if表达式直接返回结果,完全不需要return关键字——if表达式本身的值就是函数的返回值。

5.2 循环体内直接赋值

Collatz 序列练习 的官方解答 exercise.rs 中,if表达式被用在while循环体内直接给变量赋值:

/// Determine the length of the collatz sequence beginning at `n`. fn collatz_length(mut n: i32) -> u32 { let mut len = 1; while n > 1 { n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 }; len += 1; } len }

课程对应的 解答说明 明确指出了这一写法的优势:

ifexpressions:Rust'sifis an expression, meaning it produces a value. We assign the result of theif/elseblock directly ton. This is more concise than writingn = ...inside each branch.

即:n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 };比在分支内分别写n = n / 2;n = 3 * n + 1;更简洁。配套测试也验证了结果:

#[test] fn test_collatz_length() { assert_eq!(collatz_length(11), 15); }

这种“表达式即值”的风格,让数据流的每一步变换都清晰可见,是 Rust 代码的惯用写法。

六、与match的分工:什么时候用if,什么时候用match

课程在 match 表达式 一节中专门讨论了ifmatch的取舍:

  • 两分支布尔判断if {} else {}match一个bool的写法几乎等价,此时用if更自然;
  • 多分支匹配:当需要检查一个值的多个可能取值时,matchif {} else if {} else if {}链条更简洁、更安全(match强制穷尽所有可能性,且分支间不会像 C 的switch那样贯穿 fall-through)。
// match 版本:多分支时更清晰 let val = match flag { true => 1, false => 0, };

因此,本节的if知识是理解后续match的阶梯:两者同为“表达式”、同有“分支求值”的语义,只是match更擅长多分支与模式匹配。

七、课堂演示建议与易错点总结

课程为讲师提供了三条课堂演示建议,对自学者同样适用:

  1. 观察分号对分支类型的影响:在if x < 20 { "small" } else { "large" }"small"后加分号,观察类型不匹配的编译错误——直观体会“块尾表达式决定块类型”;
  2. 观察语句结尾分号的影响:删除let size = ...;末尾的分号,体会let语句的句法要求;
  3. 对比等价写法:把表达式式if改写成传统的先声明后赋值形式,感受表达式的简洁性。

汇总本节的易错点:

场景正确写法常见错误
分支类型两分支类型必须一致一个分支尾表达式加分号变为(),类型分叉报错
let绑定let x = if cond { a } else { b };以分号收尾忘记末尾分号导致语法错误
条件括号if x > 0即可误写成 C 风格if (x > 0)(不报错但非 Rust 惯例)
分支花括号if cond { ... }不可省略花括号省略花括号直接报错

八、扩展阅读

在 Comprehensive Rust 仓库中,围绕if表达式可以继续阅读:

  • Blocks and Scopes:块是表达式的容器,最后一个表达式的值决定整个块的值;
  • match 表达式:多分支表达式求值,与if互补;
  • 循环 与 break/continue:while条件本质上也是布尔表达式;
  • 函数:尾表达式返回与if表达式结合的最佳实践;
  • Collatz 练习 与 解答:在完整练习中体会if表达式的实战价值。

掌握if是理解 Rust “表达式导向”(expression-oriented)编程风格的第一步——从这里的let size = if ...到函数尾返回、再到match与闭包,Rust 的整个语言设计都围绕“一切皆表达式”展开,这正是它区别于传统命令式语言的核心哲学。

【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 11:18:46

ozip转zip:解密OPPO/Realme固件的Python实战指南

简介&#xff1a;本资源是一款专为OPPO机型刷机爱好者与固件开发者设计的ozip格式转zip格式工具包&#xff0c;解决第三方TWRP Recovery不兼容官方ozip卡刷包的痛点&#xff0c;支持直接转换后提取boot、system等关键分区文件&#xff0c;适用于刷机调试、固件分析及定制ROM开发…

作者头像 李华
网站建设 2026/9/10 11:18:40

智能服装核心技术解析与应用前景

1. 智能服装行业全景扫描 当传统纺织业遇上微电子技术&#xff0c;一场关于"可穿戴"的产业革命正在悄然发生。智能服装作为继智能手表、手环之后的下一代可穿戴设备&#xff0c;正在突破单一健康监测功能&#xff0c;向医疗康复、运动竞技、军事防护等专业领域纵深发…

作者头像 李华
网站建设 2026/9/10 11:18:39

CN68xx MIPS64交叉工具链解析:从归档到部署

简介&#xff1a;面向Cavium CN68XX系列MIPS处理器的VxWorks6.9 BSP资源包&#xff0c;专为需要在多核MIPS i64R2架构上快速搭建嵌入式系统的开发者设计。包内提供完整的板级支持包&#xff0c;覆盖启动引导、中断处理、内存管理、设备驱动、文件系统及网络协议栈等关键模块&am…

作者头像 李华
网站建设 2026/9/10 11:17:55

Python数据分析实战工作流:从环境搭建到可复现建模

简介&#xff1a;本资源是《Python数据分析实战&#xff08;第2版&#xff09;》配套源码包&#xff0c;面向Python初学者与数据科学入门者&#xff0c;系统支撑从数据获取、清洗、可视化到机器学习建模的全流程实践。压缩包共80个文件&#xff0c;含17个Jupyter Notebook&…

作者头像 李华
网站建设 2026/9/10 11:17:45

端到端公式识别:从CNN+Transformer到LaTeX生成实战

简介&#xff1a;这是一套基于 PyTorch 的端到端图像 LaTeX 公式识别项目&#xff0c;面向有一定基础的深度学习开发者与科研教育人员&#xff0c;解决从数学公式图像到可编辑 LaTeX 代码自动转换的难题。内容覆盖图像预处理、卷积神经网络特征提取、循环神经网络序列解码以及编…

作者头像 李华