Rust学习笔记:控制流——if、loop、while、for与match

上一篇我们搞定了变量、数据类型和函数,这一篇进入程序逻辑的核心——控制流。Rust 的控制流语句有一个贯穿始终的特点:它们几乎都是表达式,能返回值。这一点和 C/Java 等语言差异很大,值得单独写一篇理清楚。

本文所有代码均已实测通过,运行输出贴在对应小节末尾。


1. if 表达式

1.1 基本用法

let n = 7;
if n > 5 {
    println!("{n} 大于5");
} else {
    println!("{n} 小于等于5");
}

条件必须是 bool 类型,Rust 不会像 C 那样把 0false、把非零当 true

// if 1 { }  // ❌ 编译错误:expected `bool`, found integer

这个设计排除了 C 系语言中一大类隐式类型转换导致的 bug。

1.2 if 是表达式,可以赋值

Rust 的 if 整体是一个表达式,可以直接赋值给变量——不需要 C 语言的三元运算符 ?:

let result = if n > 5 { "大于5" } else { "小于等于5" };

每个分支的返回值类型必须一致,否则编译不过:

// let x = if true { 1 } else { "hello" };  // ❌ 类型不匹配

1.3 多分支

let grade = if n >= 9 {
    'A'
} else if n >= 7 {
    'B'
} else if n >= 5 {
    'C'
} else {
    'D'
};

运行输出:

7 大于5
分数 7 -> 等级 B

2. loop 无限循环

loop 会一直循环,直到遇到 break。它最独特的能力是 break 可以带一个返回值,这个值就是整个 loop 表达式的结果

let mut count = 0;
let result = loop {
    count += 1;
    if count == 5 {
        break count * 2;  // loop 返回 10
    }
};
println!("loop 循环了 {count} 次,返回 {result}");

这种写法在需要「重复尝试直到成功,然后取出结果」的场景下非常自然——比如重试网络请求、等待某个条件满足。

运行输出:

loop 循环了 5 次,返回 10

3. while 条件循环

和大多数语言一样,条件为真时执行循环体。Rust 的 while 没有额外的语法糖:

let mut n = 3;
while n > 0 {
    println!("{n}...");
    n -= 1;
}
println!("发射!");

运行输出:

倒计时: 3... 2... 1... 发射!

4. for 遍历

for 是 Rust 中最常用的循环——安全、简洁,不存在数组越界的风险。

4.1 遍历数组

let arr = [10, 20, 30, 40, 50];
for elem in arr {
    println!("{elem}");
}

这里 elem 是数组元素的副本(标量类型实现了 Copy)。对复杂类型,用 for elem in &arr 可以借用而不转移所有权——这一点后面所有权章节会详细展开。

4.2 Range:灵活的整数序列

// 0..5  不含 5 → 0, 1, 2, 3, 4
for i in 0..5 { }

// 0..=5 包含 5 → 0, 1, 2, 3, 4, 5
for i in 0..=5 { }

// 反向
for i in (1..=5).rev() { }  // 5, 4, 3, 2, 1

Rust 没有 C 风格的三段式 for (int i = 0; i < n; i++),Range 替代了这个角色,而且更安全——不会写错终止条件。

运行输出:

数组元素: 10 20 30 40 50
0..5:  0 1 2 3 4
0..=5: 0 1 2 3 4 5
反向:  5 4 3 2 1

5. match 模式匹配

match 是 Rust 控制流的「王牌」——比 C 的 switch 强大得多。

5.1 基本匹配

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

几个关键点:

  • _ 是通配符,匹配所有未被前面分支覆盖的值。如果去掉 _ 分支,编译器会报错——因为 num 可能是 4、5、100……
  • match 不会「穿透」(fall-through),匹配到一个分支就停,不需要 break

5.2 match 也是表达式

ifloop 一样,match 整体可以返回值:

let desc = match num {
    1 => "最小",
    2 | 3 | 5 | 7 => "质数",   // | 表示「或」
    4 | 6 | 8 | 9 | 10 => "合数",
    _ => "超出范围",
};

5.3 穷尽性检查——Rust 的安全底线

match 最强大的设计是编译器强制你处理所有可能的情况。如果漏了一个分支:

// match num {
//     1 => "一",
//     2 => "二",
// }  // ❌ 编译错误:non-exhaustive patterns

编译器会直接拒绝编译,并提示你哪些值没被覆盖。这意味着 match 本质上是编译期安全网——只要你用了 match 而不是 if-else,就永远不会漏掉边界情况。

运行输出:

三
7 是质数

6. 五种控制流对比

语句 是否表达式 典型用途
if 条件判断、分支赋值
loop 无限循环、重试逻辑、break 返回值
while 条件驱动的循环
for 遍历集合、Range
match 穷举匹配、编译器安全保障

总结

这一篇覆盖了 Rust 五种控制流:

  1. if 是表达式——不需要三元运算符,分支返回值类型必须一致,条件必须是 bool
  2. loop——break 可以带返回值,适合「循环直到成功」的场景
  3. while——和主流语言一致,没有额外概念
  4. for——配合 Range 替代 C 风格三段式 for,安全且直观
  5. match——穷尽性检查是编译期的安全网,_ 是通配符,| 表示或

下一篇即将进入 Rust 的「灵魂」——所有权、借用与生命周期。这是整个学习过程中最重要、也是最需要时间消化的一篇。

posted @ 2026-09-13 14:18  PC2005-cloud  阅读(9)  评论(0)    收藏  举报