首页 / Rust 入门教程 / while 循环

Rust 入门教程

while 循环

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

RustRust 入门教程while条件循环计数器死循环breakcontinue

本节目标:用 while 写出”只要条件为真就一直做”的循环,理解它和 loop、for 的分工,避免条件永远为真导致的死循环,并能用 break/continue 控制流程。

loop 是”无条件一直转”,上一章讲过。但很多时候你要的不是”转个不停”,而是”某个条件成立期间转,不成立就停”。这种”当……时重复”的语义,用 while 最贴切。它把”退出条件”写在循环顶部,一眼就能看出循环什么时候会停,可读性比 loop + break 好很多。

18-1 基本写法

while 后面跟一个条件。每一轮开始前,编译器先判断条件:为真就执行循环体,为假就跳出,进入后面的代码。

fn main() {
    let mut number = 3;
    while number != 0 {
        println!("{number}!");
        number -= 1;
    }
    println!("发射!");
}

这段会倒数 3!2!1!,然后打印”发射!“。循环体每轮把 number 减 1,当 number 变成 0,number != 0 为假,循环结束。注意循环条件和循环体里”让条件变假的动作”是配套的——少了后者就转个没完。

Note

if 一样,while 的条件必须是 bool。写 while number {}(number 是整数)会编译报错,因为 Rust 不认”非零即真”。要写成 while number != 0 {}while number > 0 {}。这个规矩和 C 语言不同,初学者常在这一步踩坑。

18-2 用 while 做有界计数

借助一个会变的计数器,while 能实现”重复 N 次”:

fn main() {
    let mut i = 0;
    while i < 5 {
        println!("第 {i} 次");
        i += 1;
    }
}

每轮 i 加 1,直到 i < 5 不成立为止。这能跑,但 Rust 更推荐用下一章的 for 做这种”固定次数”的循环——因为 while 写法里你要手动管 i += 1,漏写或写错就出问题。能数清楚次数的循环,for 才是更地道的选择。

18-3 经典陷阱:条件永远为真

while 最危险的坑,是条件永远为真,循环变成死循环:

let mut x = 0;
while x < 5 {
    println!("卡住了"); // 忘了 x += 1,x 永远是 0,永远 < 5
}

这种 bug 不会编译报错(语法没毛病),但运行时程序卡死,CPU 被占满。所以写 while 时务必确认:循环体里的动作最终会让条件变假。如果条件依赖某个外部事件(比如”等到用户点取消”),要确保那条事件路径确实存在、一定能发生,否则程序会一直转。

Warning

死循环不会在编译期被发现,危害比编译报错大。调试时,可以在循环体里临时打印条件变量(如 println!("x = {x}")),看它为啥一直不变。确认它最终会变假,再去掉打印。

18-4 while 和 break/continue

while 里照样能用 breakcontinue,行为和 loop 里一致。break 是”不管条件满不满足,立刻跳出整个循环”;continue 是”跳过本轮剩下的代码,直接回去判断条件、开始下一轮”。

let mut i = 0;
while i < 10 {
    i += 1;
    if i % 2 == 0 {
        continue; // 偶数跳过本轮剩余代码
    }
    println!("奇数 {i}");
}

遇到偶数 continue 跳回条件判断,所以只打印奇数。continue 不会让条件变假,它只是跳过本轮。如果你需要”中途强制停”,用 break

Warning

continue 有个隐蔽陷阱:如果它出现在”让条件变假的代码”之前,就会跳过那行,导致条件永远为真。比如 while x < 10 { if x % 2 == 0 { continue; } x += 1; }x 为偶数时会死循环——continue 跳过了 x += 1。写 continue 时务必确认条件最终能变假。

18-5 和 loop、for 怎么选

三种循环语义重叠,但有清晰分工,按语义选最贴合的:

  • loop:纯无限,靠内部 break 决定何时停。适合”先做、再判断是否继续”(如事件轮询、重试)。
  • while:“当条件为真时重复”。条件写在顶部,一眼看出循环何时结束,可读性最好。适合”次数未知、只看条件”的场景。
  • for:“对集合或区间里每个元素做一遍”。最适合遍历和固定次数,几乎不会写出死循环。

判断口诀:循环次数”跑之前就知道”吗?知道就用 for;不知道、只知道”满足某条件就停”就用 while;连条件都想写在里面就用 loop。选最贴合语义的,别人读你代码时不费劲。

18-6 while 做等待式轮询

while 很适合”轮询某个会变的状态”,比如等一个标志位被别的任务置真:

let mut ready = false;
while !ready {
    // 做点准备工作,或休眠一小会儿
    // 某个时刻 ready 被设为 true,循环自然结束
}

这类”等到某条件成立”的等待,while 表达得最自然。进阶并发章节会讲更优雅的等待机制(如通道、await),现阶段用 while 足够理解”条件驱动循环”这个模式。

18-7 while 与遍历的取舍

前面说过,固定次数的循环更推荐 for。但 while 在”条件驱动”的场景无可替代,比如读用户输入直到对方输入 quit、或轮询某个状态变化。这类”次数未知、只看条件”的任务,while 语义最贴切。

要特别强调:while 的条件在每一轮开头都会被重新求值。这意味着如果条件依赖的变量在循环体里变化了,下一轮的判断就是用新值算的。这既是它灵活的地方,也是坑的来源——你写的循环体必须真的去改变那个被判断的变量。很多死循环的根源,就是”条件里用的变量,循环体里根本没动它”,于是条件永远为真。养成习惯:写 while 时先想清楚”谁在让条件变假”,并在循环体里找到对应的那行代码。

一个常见误区是用 while 遍历数组时手动维护下标:

let a = [10, 20, 30];
let mut i = 0;
while i < a.len() {
    println!("{}", a[i]);
    i += 1;
}

这能跑,但有两个隐患:一是忘了 i += 1 就死循环;二是 a[i] 仍有越界风险(虽然 i < a.len() 守住了)。换成 for element in a 直接遍历元素,既无越界可能、也不用管下标,代码更短更安全。经验是:遍历集合用 for,单纯”条件循环”用 while

18-8 while 读输入直到合法

while 常用于”读用户输入直到合法”这类交互循环。比如不断读文本,直到用户输入 “0” 才停(示意):

use std::io;
let mut line = String::new();
while line.trim() != "0" {
    line.clear();
    io::stdin().read_line(&mut line).unwrap();
    println!("你输入了:{}", line.trim());
}

只要输入不是 “0”,循环就继续。循环次数完全未知,这种”以外部输入为终止条件”的场景,whilefor 自然得多。

Warning

交互式 while 里如果忘了”清空上次输入”或”读新输入”,可能陷入用旧值反复判断的死循环。写这类循环时确认:每轮都真正拿到了新的、可能让条件变假的数据。另外 read_line 会连换行符一起读进来,所以要 trim() 掉再比较,否则 “0\n” 永远不等于 “0”。

18-9 while 与 for 的性能差异

whilefor 在性能上几乎没差别——编译器会把它们都优化成高效的机器码,选哪个纯粹看语义是否贴切,不用担心”用错循环变慢”。经验上:遍历集合用 for,条件驱动用 while,靠内部 break 退出的用 loop。三者语义重叠,但各管一摊,选最贴合的那个,读代码的人一眼就懂循环意图。

Note

有个细微点:for 遍历数组/切片时,底层用迭代器每次取下一个元素;while 用手动下标则多一次”下标是否越界”的检查(运行时)。但 for 的迭代器版本这个检查被优化掉了,所以 for 反而常比手写 while + 下标 更优且更安全。能用 for 就优先 for

18-10 小结

while 条件 { } 在每轮开头判断条件,为真才执行;条件必须是 bool;小心漏掉让条件变假的代码导致死循环;循环体内可用 break(强制停)和 continue(跳本轮)。和 loopfor 的分工是:能数清次数用 for,条件驱动用 while,无条件死转用 loop

还有一个细节值得记住:while 的条件表达式里不能做赋值(Rust 不允许 while x = get() 这种把赋值当条件,必须用 while let 或先赋值再判断),这是它有意为之,避免把 == 误写成 = 这种经典 C 语言 bug。所以条件里只能放”判断”,不能放”赋值”,这也让 while 的语义更干净。

下一章讲 for 和区间(range),它是遍历集合和”做固定次数”最地道、最安全的写法。