Rust 控制流
程序的本质就是"做判断、重复干活、根据情况分流"。这一篇讲 Rust 的控制流:if 分支、loop/while/for 循环、以及强大的 match。Rust 控制流的一个重要特点是它们大多是表达式,有返回值——这是 Rust 的标志性设计。
1. if 表达式
Rust 的 if 和其他语言类似,但有几个细节:
fn main() {
let score = 85;
// if 表达式(条件必须是 bool,不能 0/1 隐式转换)
if score >= 90 {
println!("优秀");
} else if score >= 60 {
println!("及格");
} else {
println!("不及格");
}
// if 是表达式,有返回值!可以赋给变量
let status = if score >= 60 { "通过" } else { "挂科" };
println!("{}", status); // 通过
// 两个分支的类型必须相同
// let x = if cond { 1 } else { "two" }; // 编译错误!
}关键点:
- 条件必须是 bool:不能像 C/JS 用
if num(隐式转 bool),必须写if num != 0。这避免了"误把赋值当判断"等 bug。 - if 是表达式:有返回值,可以赋给变量。这是 Rust 比 C/Java 强的地方。
- 两个分支类型必须一致:if 返回的值类型必须相同,这是类型系统保证的。
- 不需要括号:条件不加圆括号,花括号是必需的(单行也不能省)。
2. loop 无限循环
loop 是无条件循环,类似其他语言的 while true。它配合 break 跳出:
fn main() {
// loop:无条件无限循环(类似 while true)
let mut count = 0;
loop {
count += 1;
if count >= 5 {
break; // 跳出循环
}
}
println!("count = {}", count); // 5
// loop 也是表达式,break 可以带返回值
let mut n = 0;
let result = loop {
n += 1;
if n == 10 {
break n * 2; // 返回 20
}
};
println!("result = {}", result);
// 嵌套循环用 label(标签)精确控制 break 哪一层
let mut found = false;
'outer: for i in 1..=3 {
for j in 1..=3 {
if i * j == 6 {
println!("找到 {} * {}", i, j);
found = true;
break 'outer; // 跳出外层循环
}
}
}
}loop 的几个亮点:
- break 可以带返回值:让 loop 成为有返回值的表达式,适合"反复尝试直到成功"的场景。
- 标签(label):嵌套循环时,用
'outer:给外层起名,break 'outer精确跳出哪一层。
3. while 条件循环
while 在条件为真时循环,为假时停止。用法和其他语言一样:
fn main() {
// while:条件循环,条件为 false 时停止
let mut n = 3;
while n > 0 {
println!("{}!", n);
n -= 1;
}
println!("发射!");
// 用 while 遍历集合(不如 for 优雅)
let arr = [10, 20, 30];
let mut i = 0;
while i < arr.len() {
println!("arr[{}] = {}", i, arr[i]);
i += 1;
}
// 实际几乎不用 while 遍历,用 for 更地道
}虽然可以用 while 遍历集合,但Rust 推荐用 for——更简洁,不会越界,也更能表达"遍历每个元素"的意图。
4. for 循环(最常用)
Rust 的 for 不是 C 风格的 for(init;cond;inc),而是迭代器风格——遍历任何"可迭代"的对象。这是 Rust 最常用的循环形式:
fn main() {
// for:Rust 最常用的循环(没有 C 风格的 for(init;cond;inc))
// 通过迭代器实现
// 遍历范围
for i in 0..5 {
print!("{} ", i); // 0 1 2 3 4
}
println!();
for i in 1..=3 {
print!("{} ", i); // 1 2 3
}
println!();
// 遍历数组
let nums = [10, 20, 30, 40];
for n in nums {
print!("{} ", n); // 10 20 30 40
}
println!();
// 需要索引:用 .iter().enumerate()
for (i, val) in nums.iter().enumerate() {
println!("索引 {}: 值 {}", i, val);
}
// 反向遍历
for n in (1..4).rev() {
print!("{} ", n); // 3 2 1
}
println!();
// 步长(用 step_by)
for n in (0..10).step_by(2) {
print!("{} ", n); // 0 2 4 6 8
}
}几个亮点:
- 范围 + for是写循环的标准姿势,简洁且安全(不会越界)。
- 需要索引时用
.iter().enumerate(),返回 (索引, 值) 元组。 - 反向、步长用
.rev()、.step_by(N)等,链式调用很优雅。 - for 循环背后是迭代器(Iterator)机制,性能和 while 索引一样快(零成本抽象)。
5. match 模式匹配(初识)
match 是 Rust 最强大的控制流,后面有专门一篇讲枚举和模式匹配。这里先看它的基本用法:
fn main() {
// match:Rust 最强的控制流,模式匹配
// 必须穷尽所有可能(_ 表示其他)
let num = 3;
match num {
1 => println!("一"),
2 | 3 => println!("二或三"), // | 表示或
4..=9 => println!("四到九"), // 范围模式
_ => println!("其他"),
}
// match 也是表达式,有返回值
let day = 3;
let name = match day {
1 => "周一",
2 => "周二",
3 => "周三",
4 => "周四",
5 => "周五",
_ => "周末",
};
println!("今天是{}", name);
// match 必须穷尽!漏写一个分支会编译报错
// 这是 Rust 比 switch 安全的地方:不会"漏处理"
}match 的几个重要特性:
- 必须穷尽所有可能:漏写一个分支编译报错。这是 Rust 比 C/Java switch 安全的地方——不会"漏处理某个 case"。
- 是表达式,有返回值,各分支类型要一致。
- 支持丰富模式:字面量、范围、或、解构……下一篇会深入。
6. break 和 continue
这两个是循环控制关键字,和其他语言一致:
fn main() {
// break:跳出循环
// continue:跳过本次,进入下一次
for n in 1..=10 {
if n % 2 == 0 {
continue; // 跳过偶数
}
if n > 7 {
break; // 大于 7 就停
}
println!("{}", n); // 输出 1 3 5 7
}
// 在 loop 里用 break 返回值
let mut sum = 0;
let total = loop {
sum += 1;
if sum >= 100 {
break sum; // 返回 100
}
};
println!("total = {}", total);
}- break:立即结束整个循环。在 loop 里可以带返回值。
- continue:跳过本次剩余代码,进入下一次循环。
7. if let 简写
当你只关心 match 的一种情况时,可以用 if let 简写。这是 match 的语法糖,代码更简洁。具体例子在枚举篇会看到:
- match 适合处理多种情况。
- if let 适合只关心一种情况,忽略其他。
8. Rust 没有 switch
Rust 没有 C/Java 的 switch 语句——因为 match 完全覆盖了 switch 的功能,而且更强大、更安全(强制穷尽、不会忘记 break、支持复杂模式)。习惯之后,你会发现 match 比 switch 优雅太多。
9. 控制流都是表达式
这是 Rust 反复强调的特点:if、loop、while、for、match 都是表达式,都返回值(可能是 unit ())。这意味着你可以:
- 用 if 给变量赋值:
let x = if c { 1 } else { 2 }; - 用 loop 持续尝试直到成功:
let r = loop { if ok { break val; } }; - 用 match 分派返回值:
let s = match n { 1 => "a", _ => "b" };
这种"表达式优先"的设计让 Rust 代码更紧凑,也鼓励函数式风格。
小结
这一篇你掌握了 Rust 的全部控制流:if/else(条件必须是 bool)、loop(无限循环,可返回值)、while、for(迭代器风格,最常用)、match(模式匹配,必须穷尽)。最重要的两个特点:都是表达式(有返回值)、match 比 switch 强大(强制穷尽)。下一篇讲函数——Rust 的函数有几个独特细节,比如"尾表达式即返回值"。
← 上一篇 Rust 运算符
下一篇 Rust 函数 →