Rust: Loops e iteração em Rust
Última atualização: 2026-08-26
Um loop em Rust não é apenas um simples “loop infinito” — ele “retorna” o valor do último cálculo.
Cada um dos três tipos de loops tem seu próprio caso de uso: loop loops infinitos (com valores de retorno), while loops condicionais e for iteração de conjuntos.
1. O que você vai aprender
- Use
looppara criar um loop infinito e retornar um valor - Use
whilepara loops condicionais - Use
forpara percorrer conjuntos e intervalos - Use
breakecontinuepara controlar o processo de loop - Use um rótulo de loop para sair de um loop aninhado
- Utilizando as expressões de intervalo
0..ne0..=n
2. A história de um explorador de labirintos
(1) Sofrimento: se perder em um labirinto
Alex está desenvolvendo um jogo de labirinto. O labirinto tem uma estrutura aninhada de três camadas:
Outer layer (Dungeon) -> Middle layer (Room) -> Inner layer (Treasure Chest)
O jogador precisa ir cada vez mais fundo para encontrar a saída, mas está tendo dificuldade para escrever o código:
- Depois de encontrar a chave no baú do tesouro, eu queria pular até o nível da sala — mas
breaksó consegue pular um nível - Você precisa vasculhar todos os cômodos para abrir a porta — será que deve usar
whileoufor? - O número de andares do labirinto é fixo — mas o número de salas em cada andar varia.
“Se pudéssemos identificar cada loop, poderíamos simplesmente pular para onde quiséssemos...”
(2) A solução do Rust para loops
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);
}
As etiquetas de loop do Rust (
'outer) permitembreaksair de loops em qualquer nível. Isso é mais seguro do quegoto— não salta para um local arbitrário no código, mas apenas sai do loop.
3. Comparação dos três loops
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]
| Características | loop |
while |
for |
|---|---|---|---|
| Quando usar | Condição de término indefinida | Orientado por condição | Iteração sobre um conjunto ou intervalo |
| Valor de retorno | break value Pode retornar um valor |
Não pode retornar um valor | Não pode retornar um valor |
| Infinite Loop | Nativo | while true |
Não é adequado |
| Desempenho | Ótimo (o compilador sabe que haverá um loop) | Ligeiramente pior (verifica a condição a cada vez) | Ótimo (controlado diretamente pelo iterador) |
| Casos de uso | Repetição/Polling | Espera condicional | Iteração por matrizes/vetores/intervalos |
(2) Comparando break e continue
| Palavra-chave | Função | Pode retornar um valor | Usada com tags |
|---|---|---|---|
break |
Sair do loop atual | break value; (somente no loop) |
break 'label; |
continue |
Pular o restante deste loop | Não é possível | continue 'label; |
(3) Expressões de escopo
| Notação | Significado | Inclui o valor final | Exemplo |
|---|---|---|---|
start..end |
Intervalo semiaberto | Não | 0..5 → 0, 1, 2, 3, 4 |
start..=end |
Intervalo fechado | Sim | 0..=5 → 0, 1, 2, 3, 4, 5 |
..end |
De 0 até o fim | Não | ..3 → 0, 1, 2 |
start.. |
Do início ao fim | — | 3.. → 3, 4, 5, ... |
4. Exemplos de loops
▶ Exemplo 1: Loops infinitos com loop e valores de retorno com break (Dificuldade ⭐)
// ============================================
// 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);
}
Resultado:
Loop ran 5 times, break returned: 10
Retry 3 Success on the next attempt: true
loopé a única estrutura de loop em Rust capaz de retornar um valor. Um valor de retorno pode vir diretamente após a palavra-chavebreak, sem a necessidade de uma variável adicional. Isso é muito útil no padrão “tentar até conseguir”.
▶ Exemplo 2: while Laço condicional (Dificuldade ⭐)
// ============================================
// while Loop:Countdown in Decreasing Order
// ============================================
fn main() {
let mut countdown = 5;
while countdown > 0 {
println!("Countdown: {}...", countdown);
countdown -= 1;
}
println!("Launch!");
}
Resultado:
Countdown: 5...
Countdown: 4...
Countdown: 3...
Countdown: 2...
Countdown: 1...
Launch!
whileVerifique a condição antes do início de cada iteração. Se a condição forfalse, pule todo o corpo do loop. Isso é adequado para cenários em que “o número de iterações é desconhecido, mas a condição de término é conhecida”.
▶ Exemplo 3: Iteração com for e intervalos (Dificuldade ⭐⭐)
// ============================================
// 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);
}
}
Resultado:
-- 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é a forma mais recomendada de fazer um loop em Rust. Ela evita o acesso fora dos limites e lida automaticamente com a iteração.0..né um intervalo semiaberto (excluindo n),0..=né um intervalo fechado (incluindo n)..enumerate()atribui um índice a cada elemento.
▶ Exemplo 4: Etiquetas de loop e loops aninhados (Dificuldade ⭐⭐⭐)
// ============================================
// 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);
}
}
}
Resultado:
Find the Target 5 At the location (1, 1)
Values found: 5
x=1, y=0
x=2, y=0
x=2, y=1
Sem um rótulo,
breakecontinueafetam apenas o loop mais interno. Ao adicionar um rótulo ('name), é possível controlar loops em qualquer nível. Essa é uma maneira mais controlada de “sair” do quegoto.
▶ Exemplo 5: Exercício abrangente — FizzBuzz e a tabuada (Dificuldade ⭐⭐)
// ============================================
// 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;
}
}
}
Resultado:
=== 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
O FizzBuzz é implementado de forma mais elegante usando a correspondência de padrões de tupla
match; a tabuada de multiplicação utiliza um padrão de dois níveisfor+ intervalo;while leté adequado para lidar com o padrão de loop “continuar enquanto um valor for recuperado”;loop+breaké adequado para a lógica de repetição de tentativas.
❓ Perguntas Frequentes
P: Qual é a diferença entre
loopewhile true? R:loopé a opção preferida no Rust.loopindica ao compilador: “Vou repetir o ciclo indefinidamente”, permitindo que o compilador realize otimizações mais eficazes. Além disso,looppode retornar um valor, enquantowhile truenão pode.
P: Qual é a diferença entre
for i in 0..nefor i in 0..=n? R:..denota um intervalo semiaberto (excluindo n), enquanto..=denota um intervalo fechado (incluindo n).for i in 0..3itera sobre 0, 1, 2;for i in 0..=3itera sobre 0, 1, 2, 3.
P: Ao iterar sobre um array, qual é a diferença entre &fruits e fruits.iter()? R: &fruits chama implicitamente
into_iterpara obter os elementos, enquanto fruits.iter() é mais explícito e claro. Os resultados são praticamente idênticos. A abordagem com iterador é mais explícita e mais flexível (por exemplo, chamadas encadeadas como.enumerate(),.filter(), etc.).
P: Como se usa o valor de retorno de
break? R: A instruçãobreakdentro de umalooppode retornar um valor, assim como uma função:let x = loop { break 42; };. Isso é comumente usado em situações em que é necessário “continuar tentando até que um resultado válido seja obtido”, reduzindo assim a necessidade de variáveis de estado adicionais.
P: O que devo fazer se houver muitos loops aninhados? R: Considere extrair o loop interno para uma função. No entanto, se uma estrutura aninhada for realmente necessária, rotular o loop externo é uma abordagem de “saída controlada” no estilo do Rust.
📖 Resumo
loop: Loop infinito; usebreak valuepara retornar um valorwhile: Laço condicional; verifica a condição antes de cada iteraçãofor: Iteração de conjuntos/intervalos — altamente recomendado- Expressões de intervalo:
0..5(excluindo 5),0..=5(incluindo 5) - A tag de loop
'labelpode encerrar ou pular um loop em qualquer nível breakSair do loop;continuePular o restante desta iteração
📝 Exercícios
- Dificuldade ⭐: Use
forpara percorrer0..=10, exibindo apenas os números pares (usandoif i % 2 == 0para verificar). - Dificuldade ⭐⭐: Simule o valor de retorno usando
loop+break: Encontre o primeiro valor maior que 6 em vec![1, 3, 5, 7, 9, 11] e retorne-o; se nenhum for encontrado, retorne -1. - Dificuldade ⭐⭐⭐: Use um loop
forde duas camadas para imprimir uma tabuada de 9x9, com cada linha formatada como1x1=1 1x2=2 …. Pense em como usar os rótulos do loop para controlar a lógica de quebra de linha.