控制流程
约 1988 字大约 7 分钟
2026-02-04
写程序本质上就是两件事:
- 根据条件决定走哪条路(分支)
- 让一段代码重复执行(循环)
Rust 中最常见的控制流程构造就是 if 表达式和 三种循环:loop / while / for。这篇文章会按“从能跑到写得优雅”的顺序,把它们讲成一条连续的学习路线。
0. 先记住两条 Rust 风格的规则
规则 1:if 的条件必须是 bool
Rust 不会像某些语言那样把 0/1、空字符串、空数组自动当作真假。 条件表达式的结果必须是 true 或 false。
规则 2:很多构造都是“表达式”,可以产生值
Rust 里 if 是表达式,所以可以写 let x = if ... { ... } else { ... }; 这会让代码更紧凑,但也带来一个要求:两个分支产生的值必须是同一类型。
1. 从最简单的分支开始:if / else
新建项目(可选):
cargo new branches
cd branches写入 src/main.rs:
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}运行:
cargo run发生了什么?
if后面跟一个条件:这里是number < 5- 条件为
true就执行{ ... }里的代码块 - 否则执行
else { ... }
没有 else 会怎样?
如果条件为 false,Rust 会跳过 if 块,继续执行后面的代码。
2. 最常见的新手错误:把整数当条件
下面这段不能编译:
fn main() {
let number = 3;
if number {
println!("number was three");
}
}原因很简单:number 是整数,不是布尔值。 如果你想表达“number 不是 0”,就把条件写清楚:
fn main() {
let number = 3;
if number != 0 {
println!("number was something other than zero");
}
}经验:Rust 的“显式”会让代码更可靠。你看到条件,就能明确知道程序为什么进入这个分支。
3. 多条件分支:else if(顺序很重要)
当条件不止一个时可以这样写:
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}关键点:只执行“第一个为真”的分支
- Rust 会从上往下检查
- 一旦命中一个
true,就不会再检查后面的条件
因此 6 同时能被 3 和 2 整除,但只会打印 divisible by 3,因为那条分支更靠前。
当
else if链条越来越长时,可读性会变差。后续遇到“多分支 + 不同情况”的场景,通常会使用更强的分支构造(例如match),不过这篇文章先把if和循环讲扎实。
4. 把 if 当成值来用:let 右侧的 if
因为 if 是表达式,你可以这样写:
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}这里发生了什么?
- 如果
condition为真,if表达式的结果是5 - 否则结果是
6 - 这个结果被赋值给
number
必须同一类型:否则编译失败
下面这段不能编译:
fn main() {
let condition = true;
let number = if condition { 5 } else { "six" };
println!("The value of number is: {number}");
}原因:if 分支返回 i32,else 分支返回 &str,类型不一致。 Rust 需要在编译期确定 number 的唯一类型。
经验:当你想用
if表达式生成一个值时,提前想好“两个分支最终要得到同类东西”。
进入循环:让代码重复执行
Rust 有三种循环:loop / while / for。它们解决同一类问题,但适合的场景不同。
5. loop:最原始的“无限循环”,必须手动停
loop 的语义非常直接:一直重复,直到你明确让它停止。
fn main() {
loop {
println!("again!");
}
}运行后会不停输出,终端一般用 Ctrl + C 中断。
5.1 break:退出循环
你可以用 break 在某个条件满足时停止循环:
fn main() {
let mut n = 0;
loop {
n += 1;
if n == 3 {
break;
}
println!("n = {n}");
}
println!("done");
}5.2 continue:跳过本轮剩余代码,进入下一轮
fn main() {
let mut n = 0;
loop {
n += 1;
if n % 2 == 0 {
continue; // 偶数跳过
}
println!("odd n = {n}");
if n == 5 {
break;
}
}
}经验:
loop很适合“先做一件事,失败就重试”的结构,比如读输入、解析、检查、再决定是否退出。
6. loop 还能“返回值”:break 值
这是 Rust 很有特色的地方:break 可以携带一个值,作为整个 loop 表达式的结果。
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 把值带出去
}
};
println!("The result is {result}");
}这段代码的阅读方式是:
- 循环一直跑
- 当
counter == 10时停止 - 停止时把
counter * 2作为result的值
break vs return
break:只退出当前循环return:直接退出当前函数(不管你在多少层循环里)
7. 嵌套循环时,break 到底退出哪一层?用“循环标签”讲清楚
默认情况下:
break/continue只作用于最内层循环
如果你需要跳出外层循环,可以给外层循环加标签(标签以单引号开头):
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break; // 只退出内层 loop
}
if count == 2 {
break 'counting_up; // 退出外层 loop
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
}经验:标签不是常用武器,但在“多层循环 + 需要精准跳出”的场景非常干净。
8. while:当“条件为真就继续”,条件为假就停止
很多循环都是这种模式: “只要还满足条件,就继续跑;否则停止”。
用 while 写倒计时:
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("LIFTOFF!!!");
}为什么不用 loop + if + break?
当然能写,但会更啰嗦、嵌套更深。 while 就是把最常见的“条件循环”结构变成了语言级构造,读起来更直接。
9. for:遍历集合的首选(更安全、更简洁)
9.1 先看一个“容易出错”的 while 遍历数组
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index += 1;
}
}这段代码的问题是:
5是手写的,如果数组长度改了,你可能忘记同步修改- 条件写错会导致越界 panic 或漏掉元素
- 每次循环都要检查索引边界,结构更繁琐
9.2 用 for 遍历:不写索引,也不怕长度变化
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}优点:
- 更短
- 更不容易出错
- 通常更高效(不需要每轮都手动做索引比较逻辑)
经验:在 Rust 中,只要是“遍历集合”,优先
for。
10. for 也能做“跑固定次数”:用范围 Range
倒计时用 for 可以写得更顺:
fn main() {
for number in (1..4).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}解释一下:
1..4生成 1、2、3(右边不包含 4).rev()把顺序反转成 3、2、1for逐个取出并执行循环体
11. 选择哪种循环?一张决策表解决 80% 纠结
- 需要无限重试,直到某个时刻成功或手动退出 →
loop- 常见:读输入 → 解析 → 不合法就
continue→ 合法且满足条件就break
- 常见:读输入 → 解析 → 不合法就
- 条件控制“满足就继续、不满足就停” →
while- 常见:倒计时、状态轮询(简单版)
- 遍历集合 / 运行固定次数 →
for- 常见:数组、向量、范围循环,几乎都是首选
12. 小练习(把本章知识变成手感)
- 写一个程序:
let n = 10;- 用
if/else if/else判断 n 能否被 2/3/5 整除,输出第一条命中的规则。
- 写一个
loop:- 从 1 加到 100
- 遇到 17 的倍数跳过(
continue) - 当总和超过 500 时停止,并用
break sum把 sum 作为结果返回。
- 写一个
for:- 遍历数组
[3, 1, 4, 1, 5] - 打印每个元素的平方。
- 遍历数组
贡献者
flycodeu
版权所有
版权归属:flycodeu
