Rust: Rust Loops and Iteration

Last updated: 2026-08-26

A loop in Rust isn't just a simple "infinite loop"—it "spits out" the value of the last calculation.

Each of the three types of loops has its own use case: loop infinite loops (with return values), while conditional loops, and for set iteration.


1. What You'll Learn



2. The Story of a Maze Explorer

(1) Suffering: Getting Lost in a Maze

Alex is developing a maze game. The maze has a three-layered nested structure:

TEXT 📖 Display only
Outer layer (Dungeon) -> Middle layer (Room) -> Inner layer (Treasure Chest)

The player needs to go deeper and deeper to find the exit, but he finds it difficult to write the code:

"If we could label each loop, we could just jump to wherever we want..."

(2) Rust's Solution for Loops

RUST
fn main() {
    let mut found_exit = false;
    let maze = [
        ["empty", "empty", "key"],
        ["empty", "monster", "empty"],
        ["exit", "empty", "trap"],
    ];

    // Outer Label 'outer Naming Dungeon Cycles
    'outer: for (row, floor) in maze.iter().enumerate() {
        println!("Enter the dungeon, Floor #{}", row + 1);
        for (col, room) in floor.iter().enumerate() {
            match *room {
                "exit" => {
                    println!("  Find the Exit!Location: ({}, {})", row, col);
                    found_exit = true;
                    break 'outer;  // Exit two nested loops immediately
                }
                "key" => println!("  Get the keys (Location: {},{})", row, col),
                "monster" => println!("  There's a monster!Skip this room"),
                _ => println!("  Vacant Room {}", col),
            }
        }
    }

    println!("Have you found the exit?: {}", found_exit);
}

Rust's loop labels ('outer) allow break to break out of loops at any level. This is safer than goto—it doesn't jump to an arbitrary location in the code, but only breaks out of the loop.



3. Comparison of the Three Loops

100%
graph TB
    A[Rust Loop] --> B[loop: Infinite Loop]
    A --> C[while: Conditional Loops]
    A --> D[for: Set Iteration]
    B --> E[Until break up to and including]
    B --> F[Available break Return Value]
    C --> G[Check the condition before each loop]
    D --> H[Iterating Through a Set Automatically/Scope]
    D --> I[Most Commonly Used,Safest]
Characteristics loop while for
When to Use Undefined termination condition Condition-driven Iterating over a set or range
Return Value break value May return a value Cannot return a value Cannot return a value
Infinite Loop Native while true Not suitable
Performance Optimal (the compiler knows it will loop) Slightly worse (checks the condition each time) Optimal (directly driven by the iterator)
Use Cases Retry/Polling Conditional Wait Iterate Through Arrays/Vectors/Ranges

(2) Comparing break and continue

Keyword Function Can Return a Value Used With Tags
break Exit the current loop break value; (loop only) break 'label;
continue Skip the remainder of this loop Cannot continue 'label;

(3) Scope Expressions

Notation Meaning Includes End Value Example
start..end Semi-open interval No 0..5 → 0, 1, 2, 3, 4
start..=end Closed interval Yes 0..=5 → 0, 1, 2, 3, 4, 5
..end From 0 to end No ..3 → 0, 1, 2
start.. From start to end 3.. → 3, 4, 5, ...


4. Loop Examples

▶ Example 1: Infinite loops with loop and return values with break (Difficulty ⭐)

Output:

TEXT 📖 Display only
Loop ran 5 times, break returned: <result>
Retry 0 Success on the next attempt: <success>
RUST
// ============================================
// loop Loop:A simulation of the "Guess the Number" game"Let's try again"
// ============================================

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;
        if counter == 5 {
            break counter * 2;  // break Can have a return value!
        }
    };

    println!("Loop ran 5 times, break returned: {}", result);

    // Real-World Scenarios:Keep trying until you succeed
    let mut attempts = 0;
    let success = loop {
        attempts += 1;
        if attempts >= 3 {
            break true;
        }
        // Simulate a failed operation,Keep trying
    };
    println!("Retry {} Success on the next attempt: {}", attempts, success);
}

Output:

TEXT 📖 Display only
Countdown: 5...
Launch!





loop is the only loop structure in Rust that can return a value. A return value can follow the break keyword directly, without the need for an additional variable. This is very useful in the "try-until-successful" pattern.


▶ Example 2: while Conditional Loop (Difficulty ⭐)

Output:

TEXT 📖 Display only
Countdown: 5...
Launch!
RUST
// ============================================
// while Loop:Countdown in Decreasing Order
// ============================================

fn main() {
    let mut countdown = 5;

    while countdown > 0 {
        println!("Countdown: {}...", countdown);
        countdown -= 1;
    }

    println!("Launch!");
}

Output:

TEXT 📖 Display only
Countdown: 5...
Countdown: 4...
Countdown: 3...
Countdown: 2...
Countdown: 1...
Launch!

Output:

TEXT 📖 Display only
-- Scope 0..5 --

while Check the condition before the start of each iteration. If the condition is false, skip the entire loop body. This is suitable for scenarios where "the number of iterations is unknown, but the termination condition is known."


▶ Example 3: Iterating with for and Ranges (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
-- Scope 0..5 --
<i> 

-- Scope 0..=5 --
<i> 

-- List of Fruits --
<fruit>
-- Indexed Iteration --
Fruit #<index>: <fruit>
RUST
// ============================================
// for Loop:Iteration Range,Arrays and Strings
// ============================================

fn main() {
    // 1. Range Iteration: 0..5 is 0 to 4 (Excludes 5)
    println!("-- Scope 0..5 --");
    for i in 0..5 {
        print!("{} ", i);
    }
    println!();

    // 2. Closing Range:0..=5 Includes 5
    println!("-- Scope 0..=5 --");
    for i in 0..=5 {
        print!("{} ", i);
    }
    println!();

    // 3. Iterate through an array
    let fruits = ["apple", "banana", "cherry"];
    println!("-- List of Fruits --");
    for fruit in &fruits {
        println!("{}", fruit);
    }

    // 4. Indexed Iteration(enumerate)
    println!("-- Indexed Iteration --");
    for (index, fruit) in fruits.iter().enumerate() {
        println!("Fruit #{}: {}", index, fruit);
    }
}

Output:

TEXT 📖 Display only
-- Scope 0..5 --
0 1 2 3 4
-- Scope 0..=5 --
0 1 2 3 4 5
-- List of Fruits --
apple
banana
cherry
-- Indexed Iteration --
Fruit #0: apple
Fruit #1: banana
Fruit #2: cherry

for is the most recommended way to loop in Rust. It prevents out-of-bounds access and automatically handles iteration. 0..n is a half-open interval (excluding n), 0..=n is a closed interval (including n). .enumerate() assigns an index to each element.


▶ Example 4: Loop Labels and Nested Loops (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
Find the Target 5 At the location (<i>, <j>)
Values found: 0
x=<x>, y=<y>
RUST
// ============================================
// Loop Label:break 'label Breaking Out of Multiple Levels of Nesting
// ============================================

fn main() {
    let matrix = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
    ];

    let mut found = 0;

    // 'search Outer Loop for Tag Marking
    'search: for (i, row) in matrix.iter().enumerate() {
        for (j, &val) in row.iter().enumerate() {
            if val == 5 {
                println!("Find the Target 5 At the location ({}, {})", i, j);
                found = val;
                break 'search;  // Exit two nested loops immediately!
            }
        }
    }

    println!("Values found: {}", found);

    // continue It can also be used in conjunction with tags.
    'outer: for x in 0..3 {
        for y in 0..3 {
            if x == y {
                continue 'outer;  // Skip the remaining inner layers,Continue to the next outer layer
            }
            println!("x={}, y={}", x, y);
        }
    }
}

Output:

TEXT 📖 Display only
Find the Target 5 At the location (1, 1)
Values found: 5
x=1, y=0
x=2, y=0
x=2, y=1

Without a label, break and continue only affect the innermost loop. By adding a label ('name), you can control loops at any level. This is a more controlled way to "break out" than goto.


▶ Example 5: Comprehensive Exercise—FizzBuzz and the Multiplication Table (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
=== FizzBuzz (1-30) ===
FizzBuzz 
Fizz 
Buzz 
<n> 



=== The 9×9 Multiplication Table ===
<i>×<i * j>=<j>


=== while let Simulated Read ===
Encountered a termination signal,Stop Processing
Projects in Progress: <item>

=== loop Retry Mode ===
Connection Results: <attempts>
Attempt #0 to connect...
RUST
// ============================================
// Comprehensive Cycle Practice:FizzBuzz + The 9×9 Multiplication Table
// ============================================

fn main() {
    println!("=== FizzBuzz (1-30) ===");
    for n in 1..=30 {
        match (n % 3, n % 5) {
            (0, 0) => print!("FizzBuzz "),
            (0, _) => print!("Fizz "),
            (_, 0) => print!("Buzz "),
            _ => print!("{} ", n),
        }
        if n % 10 == 0 { println!(); }
    }
    println!();

    println!("\n=== The 9×9 Multiplication Table ===");
    for i in 1..=9 {
        for j in 1..=i {
            print!("{}×{}={:<4}", j, i, i * j);
        }
        println!();
    }

    println!("\n=== while let Simulated Read ===");
    let mut queue = vec![10, 20, 30, 40, 0];
    while let Some(item) = queue.pop() {
        if item == 0 {
            println!("Encountered a termination signal,Stop Processing");
            break;
        }
        println!("Projects in Progress: {}", item);
    }

    println!("\n=== loop Retry Mode ===");
    let attempts = try_connect(3);
    println!("Connection Results: {}", attempts);
}

fn try_connect(max_retries: u32) -> bool {
    let mut attempt = 0;
    loop {
        attempt += 1;
        println!("Attempt #{} to connect...", attempt);
        if attempt >= max_retries {
            break true;
        }
    }
}

Output:

TEXT 📖 Display only
=== FizzBuzz (1-30) ===
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 
11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz 
Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 

=== The 9×9 Multiplication Table ===
1×1=1   
1×2=2   2×2=4   
1×3=3   2×3=6   3×3=9   
1×4=4   2×4=8   3×4=12  4×4=16  
1×5=5   2×5=10  3×5=15  4×5=20  5×5=25  
1×6=6   2×6=12  3×6=18  4×6=24  5×6=30  6×6=36  
1×7=7   2×7=14  3×7=21  4×7=28  5×7=35  6×7=42  7×7=49  
1×8=8   2×8=16  3×8=24  4×8=32  5×8=40  6×8=48  7×8=56  8×8=64  
1×9=9   2×9=18  3×9=27  4×9=36  5×9=45  6×9=54  7×9=63  8×9=72  9×9=81  

=== while let Simulated Read ===
Projects in Progress: 40
Projects in Progress: 30
Projects in Progress: 20
Projects in Progress: 10
Encountered a termination signal,Stop Processing

=== loop Retry Mode ===
Attempt #1 to connect...
Attempt #2 to connect...
Attempt #3 to connect...
Connection Results: true

FizzBuzz is more elegantly implemented using match tuple pattern matching; the multiplication table uses a two-level for + range; while let is suitable for handling the "continue as long as a value is retrieved" loop pattern; loop + break is suitable for retry logic.


❓ FAQ

Q What is the difference between loop and while true?
A loop is the preferred choice in Rust.
Q What is the difference between for i in 0..n and for i in 0..=n?
A .. denotes a half-open interval (excluding n), while ..= denotes a closed interval (including n).
Q When iterating over an array, what is the difference between &fruits and fruits.iter()?
A &fruits implicitly calls into_iter to borrow the elements, while fruits.iter() is more explicit and clearer.
Q How do you use the return value of break?
A The break statement in a loop can return a value just like a function: let x = loop { break 42; };.
Q What should I do if there are too many nested loops?
A Consider extracting the inner loop into a function.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Use for to iterate through 0..=10, printing only even numbers (using if i % 2 == 0 to check).
  2. Difficulty ⭐⭐: Simulate the return value using loop + break: Find the first value greater than 6 in vec![1, 3, 5, 7, 9, 11] and return it; if none is found, return -1.
  3. Difficulty ⭐⭐⭐: Use a double-layered for loop to print a 9x9 multiplication table, with each row formatted as 1x1=1 1x2=2 …. Think about how to use loop labels to control the line-breaking logic.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏