首页 / Rust 入门教程 / loop 无限循环

Rust 入门教程

loop 无限循环

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

RustRust 入门教程loop无限循环breakcontinue控制流

本节目标:用 loop 写出无条件无限循环,学会用 break 跳出、continue 跳过本次,并掌握把 loop 当表达式、通过 break 带回返回值;知道它和 while/for 各自适合什么场合。

有些任务天然就是”一直做,直到某个条件才停”。比如监听用户输入、轮询一个状态、或者一个”重试直到成功”的逻辑。Rust 用 loop 关键字表达这种”无条件、一直循环”的结构。它最简单,也最灵活——停不停、什么时候停,全靠你在里面自己控制。

17-1 loop 是什么

loop 就是最简单的无限循环:只要进去了,就一遍遍地执行花括号里的代码,除非遇到 break(或程序被强制结束)。

fn main() {
    let mut count = 0;
    loop {
        count += 1;
        println!("第 {count} 次");
        if count >= 3 {
            break;
        }
    }
}

上面的循环会打印三次后停下。注意 loop 本身没有写在它后面的条件——它不像 while 那样”条件为真才继续”,它就是”一直转”,转不转得停,取决于你有没有在里面写 break

Warning

loop 一定要在循环体里安排好”出口”。如果忘了写 break,或者 break 的条件永远不满足,这个循环就真的永不停止,会一直占着一个 CPU 核心空转。新手调试时最容易写出这种”停不下来”的代码,发现终端刷屏就 Ctrl-C 强行中断。

17-2 break 跳出整个循环

break 的意思是”立刻结束当前这层循环,跳到循环后面的代码”:

fn main() {
    let mut n = 0;
    loop {
        n += 1;
        if n == 5 {
            break;
        }
        println!("n = {n}");
    }
    println!("循环结束,最终 n = {n}");
}

这段代码会在 n 等于 5 时跳出,所以只打印 1、2、3、4,然后打印”循环结束”。break 一旦执行,循环当场终止,后面的轮次都不再跑。这里 n 是在循环外声明的 mut 变量,所以跳出后还能用它的终值——这正是”先循环累加、再在循环外用结果”的常见模式。

17-3 continue 跳过本次,进入下一轮

continuebreak 不一样:它不结束循环,只是”这一轮我不干了,直接开始下一轮”。

fn main() {
    let mut n = 0;
    loop {
        n += 1;
        if n > 5 {
            break;
        }
        if n % 2 == 0 {
            continue; // 偶数跳过,不打印
        }
        println!("奇数:{n}");
    }
}

这里当 n 是偶数时遇到 continue,直接跳回循环开头、println! 那行被跳过,于是只打印 1、3、5。continue 适合”某些情况这一轮不需要处理”的场景,比如遍历一堆数据、跳过无效的那些。

17-4 loop 是表达式,break 能带返回值

这是 loop 最有用的一点:loop 是个表达式,它能产出一个值,而这个值由 break 决定。

fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    println!("结果是 {result}"); // 20
}

counter 到 10 时,break counter * 2 把 20 作为整个 loop 表达式的值,赋给 resultbreak 后面跟的那个值,就是循环”算出来交出去”的结果。这比在循环外先声明一个变量、再在循环里给它赋值要优雅——值就诞生在循环退出的那一刻。

Note

break 后面跟不跟值都行。单独写 break; 就是纯粹跳出、不带值,整个循环表达式的类型就是单元类型 ()。需要把循环算出的结果带出来时,才写 break 值;

17-5 嵌套循环与标签 break

当循环套循环时,break 默认只跳出最里那一层。如果想从内层直接跳出外层,得给外层循环贴个”标签”:

fn main() {
    let mut found = false;
    'outer: loop {
        let mut i = 0;
        loop {
            i += 1;
            if i == 3 {
                found = true;
                break 'outer; // 直接跳出外层
            }
        }
    }
    println!("找到了吗?{found}");
}

标签写在单引号里(如 'outer),放在 loop 前面;break 'outer 就表示”跳出贴了这个标签的那层循环”。嵌套深的时候这个技巧能省掉一堆标志变量。不过日常代码里嵌套循环不该太多,真遇到复杂控制流,多半是逻辑该拆了。

17-6 loop vs while vs for

三种循环怎么选,是个高频问题。一句话心法:

  • loop:你不知道要转多少圈,唯一明确的就是”在某个内部条件满足时停下”。比如重试逻辑、事件监听。它最通用,但出口要自己管。
  • while 条件:循环次数不固定,但”继续与否”可以用一个条件清楚描述(如”队列非空就继续”)。
  • for 元素 in 集合:你就是要遍历一个集合里的每一个元素。这是 Rust 里用得最多的循环,安全又简洁。
Tip

经验法则:凡是”遍历集合”,无脑用 for,别用 loop+手动加索引。凡是”条件为真就继续”,用 whileloop+if+break 读起来更直白。只有当”何时停”不好用单个条件表达、得在循环中间多处判断时,loop 才最顺手。刚学会 loop 容易啥都拿它写,克制一下。

17-7 你可能会踩的坑

  • 坑一:忘了 break,循环停不下来。写完 loop 先确认”里面一定会在某条路径上 break”。
  • 坑二:break 带了值,但有的分支只写 break; 不带值,导致循环表达式类型不一致,编译报错。要么都带、要么都不带。
  • 坑三:在 loop 里改的变量忘了声明 mut,结果 counter += 1 报错”不能修改不可变变量”。
Warning

别为了”显得高级”而滥用 loop。很多时候 whilefor 一句话就能表达清楚,可读性更好。循环的本质是”重复”,选最贴合你意图的那个,读代码的人(包括未来的你)会感激。

17-8 循环里访问外层变量与作用域

循环体内部可以读写外层定义的变量,循环不会创建新的”变量作用域墙”——只要那个变量在循环之前声明、且需要修改时带了 mut,就能在循环里累加、拼接、标记状态。常见模式:用 let mut sum = 0; 在外层,循环里 sum += item; 累积;或者用 let mut found = false; 记录”是否找到”。理解这一点,你就能用循环做”遍历 + 累积结果”这类最有价值的事。

Note

循环可以嵌套:外层 for 遍历行、内层 for 遍历列,构成二维遍历。嵌套时如果只想跳出内层或外层,记得前面讲的 '标签 语法——给外层循环起个名,再 break '标签; 一次跳出多层,否则 break 只作用于最内层。

另外,loop 表达式的返回值类型由 break 值 决定,所有 break 分支带的值类型必须一致,否则编译器无法推断”这个循环最终算出什么”。如果循环有的分支 break 5、有分支 break "ok",就会报类型不匹配——保持各分支返回同类型即可。

17-9 loop 表达式带值的完整例子

理论说完,看一个完整的真实场景:从 1 开始累加,直到和超过 100,返回那个整数。用 loop 表达式一气呵成:

fn main() {
    let mut sum = 0;
    let target = 100;
    let result = loop {
        sum += 1;
        if sum * (sum + 1) / 2 > target {
            break sum; // 把当前 sum 作为结果带出
        }
    };
    println!("第一个使累加和超过 {target} 的整数是 {result}");
}

这里 loop 整体产出一个值,赋给 result,全程没有在循环外先声明一个”答案变量”再回头赋值。这种”循环即计算、break 即返回”的写法,是 loop 作为表达式最优雅的用武之地。你以后写”找第一个满足条件的数""重试直到成功”这类逻辑时,会反复用到它。

Note

对比一下:如果用 while,你得先 let mut result = 0;,再在循环里 result = sum; break;,多一个可变变量、多一步显式赋值。功能一样,但 loop 表达式把”结果”和”退出”绑成了同一件事,代码更紧凑,意图也更清楚——“我循环就是为了算出这个值”。

17-10 小结

loop 是无条件无限循环,靠 break 跳出、continue 跳到下一轮;它还是表达式,break 值 能把循环算出的结果带出来;嵌套时用 '标签 控制跳出哪一层。三种循环里 loop 最通用但最需自律。下一章讲 while——当”继续条件”能一句话说清时,它比 loop 更直观。