首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >03-Rust 教程 - 流程控制

03-Rust 教程 - 流程控制

作者头像
LarryLan
发布2026-03-30 18:08:02
发布2026-03-30 18:08:02
1030
举报

Rust 教程 - 流程控制

程序界的"如果...就...":让你的代码学会做决定


🎬 引入

想象一下,你早上起床后要做一系列决定:

  • 如果下雨了,带伞
  • 否则戴墨镜耍酷
  • 只要还有时间,吃个早饭
  • 对于每一片面包,涂上果酱

看,你的一天就是由各种"条件判断"和"循环"组成的!编程也是一样。

在 Rust 里,流程控制就是你的代码学会"思考"和"重复做事"的能力。今天咱们就来聊聊 Rust 是怎么做决定的。

剧透预警:Rust 的 if 居然是个表达式,不是语句!这意味着它可以返回值。是不是很反直觉?别慌,看完这篇你就明白了。


📌 核心概念

条件判断:if/else

Rust 的条件判断和其他语言长得差不多,但有个关键区别

代码语言:javascript
复制
// Rust 的 if 是表达式,可以返回值!
let result = if condition {  } else {  };

生活化类比

  • if/else 就像你妈问你:"考了多少分?"
    • 如果 ≥90 分 → "真棒!奖励你玩手机"
    • 否则 → "去写作业!"
  • if 是表达式 意味着整个 if 结构会产生一个值,就像自动售货机投币后吐出一瓶饮料

循环三剑客

Rust 有三种循环方式,各有各的用处:

循环类型

用途

生活类比

loop

无限循环,直到手动停止

跑步机:你不按停止,它就一直转

while

条件循环,条件为真时继续

吃自助餐:只要还能吃,就继续拿

for

迭代循环,遍历集合

点名:把名单上的名字一个个念出来

if let:简洁版条件判断

当你只关心"匹配成功"的情况时,if let 让你少写一堆代码。就像你只关心"快递到了",不关心"快递没到"时该干嘛。


💻 代码示例

1. if/else 基础用法

代码语言:javascript
复制
fn main() {
    let temperature = ;
    
    // 基础 if/else
    if temperature >  {
        println!("热成狗了,开空调!");
    } else if temperature <  {
        println!("冻成冰棍了,穿秋裤!");
    } else {
        println!("温度刚刚好,出去浪!");
    }
}

逐行解释

  • let temperature = 25; — 定义温度变量
  • if temperature > 30 — 如果温度大于 30
  • else if — 否则如果(可以链式调用)
  • else — 以上都不满足时的默认情况

注意:Rust 的条件不需要括号if (x > 0) 是错误的,应该是 if x > 0。编译器会告诉你:

代码语言:javascript
复制
error: expected `{`, found `>`
 --> src/main.rs:4:18
  |
4 |     if (temperature > 30) {
  |                  ^ expected `{`

人话翻译:大哥,Rust 的 if 后面不需要括号,直接跟条件就行!

2. if 作为表达式(重点!)

代码语言:javascript
复制
fn main() {
    let number = ;
    
    // if 是表达式,可以返回值!
    let description = if number %  ==  {
        "偶数"// 这个值会被返回
    } else {
        "奇数"// 这个值也会被返回
    };
    
    println!("{} 是 {}", number, description);
    // 输出:7 是 奇数
    
    // 甚至可以嵌套使用
    let result = if number >  {
        if number %  ==  {
            "大于 5 的偶数"
        } else {
            "大于 5 的奇数"
        }
    } else {
        "小于等于 5"
    };
    
    println!("{}", result);
}

关键点

  • if 和 else 分支必须返回相同类型的值
  • 最后一个表达式的值就是整个 if 表达式的返回值
  • 不需要 return 关键字

3. if let 简洁写法

代码语言:javascript
复制
fn main() {
    let config_max = Some(3u8);
    
    // 传统写法:match 匹配所有情况
    match config_max {
        Some(max) => println!("最大值是:{}", max),
        _ => (),  // 其他情况啥也不干
    }
    
    // 简洁写法:if let 只关心匹配成功的情况
    if let Some(max) = config_max {
        println!("最大值是:{}", max);
    }
    // 其他情况自动忽略,不用写 _ => ()
    
    // 还可以加 else
    let coin = Some("heads");
    if let Some(side) = coin {
        println!("正面:{}", side);
    } else {
        println!("反面或者没有硬币");
    }
}

使用场景

  • 你只关心一种匹配情况
  • 其他情况不需要处理或者已经有默认值
  • 代码更简洁,可读性更好

4. loop 无限循环

代码语言:javascript
复制
fn main() {
    let mut counter = ;
    
    // loop 会一直循环,直到遇到 break
    let result = loop {
        counter += ;
        
        if counter ==  {
            break counter * ;  // 可以带返回值!
        }
    };
    
    println!("循环结束,result = {}", result);
    // 输出:循环结束,result = 20
}

特点

  • loop无限循环,必须用 break 退出
  • break 可以返回值,这是 Rust 独有的特性
  • 适合需要精确控制退出时机的场景

新手坑:忘记写 break,程序变成死循环!

代码语言:javascript
复制
fn main() {
    loop {
        println!("我要打印一万年...");
        // 忘记写 break 了!
        // 按 Ctrl+C 强制终止吧...
    }
}

5. while 条件循环

代码语言:javascript
复制
fn main() {
    let mut number = ;
    
    // 当条件为真时,一直循环
    while number >  {
        println!("{}!", number);
        number -= ;
    }
    
    println!("发射!🚀");
    // 输出:
    // 3!
    // 2!
    // 1!
    // 发射!🚀
    
    // while 也可以遍历(但不推荐)
    let mut arr = [, , , , ];
    let mut index = ;
    
    while index < arr.len() {
        println!("arr[{}] = {}", index, arr[index]);
        index += ;
    }
}

vs for 循环

  • while 需要手动管理计数器,容易出错
  • for 更简洁、更安全(后面会讲)

6. for 迭代循环(最常用!)

代码语言:javascript
复制
fn main() {
    // 遍历数组
    let arr = [, , , , ];
    
    for element in arr.iter() {
        println!("元素:{}", element);
    }
    
    // 遍历范围(超好用!)
    for number in .. {
        println!("计数:{}", number);
        // 输出:1, 2, 3(不包含 4!)
    }
    
    // 包含终点的范围
    for number in ..= {
        println!("包含终点:{}", number);
        // 输出:1, 2, 3, 4
    }
    
    // 反向遍历
    for number in (..).rev() {
        println!("倒数:{}", number);
        // 输出:3, 2, 1
    }
}

范围语法

  • 1..4 — 左闭右开,包含 1 不包含 4(类似 Python)
  • 1..=4 — 左右都闭,包含 1 和 4
  • .rev() — 反向迭代器

新手坑:忘记 iter() 导致所有权被移动!

代码语言:javascript
复制
fn main() {
    let arr = [, , ];
    
    // ❌ 错误:arr 的所有权被移动了
    for element in arr {
        println!("{}", element);
    }
    // println!("{:?}", arr);  // 编译错误!arr 不能用了
    
    // ✅ 正确:使用 iter() 借用
    for element in arr.iter() {
        println!("{}", element);
    }
    // arr 还可以继续使用
    println!("{:?}", arr);
}

7. 循环标签(高级用法)

代码语言:javascript
复制
fn main() {
    // 给循环加标签,可以从外层循环 break
    'counting_up: for i in ..= {
        for j in ..= {
            if j ==  {
                // 从外层循环 break
                break 'counting_up;
            }
            println!("i = {}, j = {}", i, j);
        }
    }
    // 输出:
    // i = 1, j = 1
    // (j=2 时直接跳出外层循环)
}

使用场景:嵌套循环时需要从内层跳出外层


🐛 常见坑点

坑点 1:忘记返回值类型一致

代码语言:javascript
复制
fn main() {
    let number = ;
    
    // ❌ 错误:if 和 else 返回不同类型
    let description = if number %  ==  {
        "偶数"// &str 类型
    } else {
        // i32 类型!编译器会炸
    };
}

编译器错误

代码语言:javascript
复制
error[E0308]: `if` and `else` have incompatible types
 --> src/main.rs:7:9
  |
4 |       let description = if number % 2 == 0 {
  |  _______________________-
5 | |         "偶数"
  | |         ------ expected because of this
6 | |     } else {
7 | |         0
  | |         ^ expected `&str`, found integer
  | |_________|
  | 

人话翻译:if 和 else 必须返回相同类型!你不能一边返回字符串,一边返回数字。

修复

代码语言:javascript
复制
let description = if number %  ==  {
    "偶数"
} else {
    "奇数"// 统一返回 &str
};

坑点 2:忘记加分号

代码语言:javascript
复制
fn main() {
    let x = ;
    
    // ❌ 错误:if 表达式后面多了一个分号
    let y = if x >  {
        x + ;  // 这个分号让返回值变成了 ()
    } else {
        x - 
    };
    // y 的类型变成了 (),不是你想要的!
}

编译器错误

代码语言:javascript
复制
error[E0308]: `if` and `else` have incompatible types
 --> src/main.rs:6:9
  |
4 |       let y = if x > 3 {
  |  _____________-
5 | |         x + 1;
  | |              - help: remove this semicolon
  | |______________|
  |                expected integer, found `()`

人话翻译:花括号里最后一个表达式后面的分号会把它变成 () 类型。去掉分号!

坑点 3:while 循环条件错误

代码语言:javascript
复制
fn main() {
    let mut i = ;
    
    // ❌ 错误:忘记更新 i,死循环!
    while i <  {
        println!("i = {}", i);
        // i += 1;  // 忘记写了!
    }
    // 程序会一直打印 i = 0...
}

最佳实践:能用 for 就别用 while

代码语言:javascript
复制
// ✅ 更好:用 for 循环
for i in .. {
    println!("i = {}", i);
}

坑点 4:for 循环中修改集合

代码语言:javascript
复制
fn main() {
    let mut numbers = vec![, , , , ];
    
    // ❌ 错误:在遍历时修改集合
    for num in numbers.iter_mut() {
        *num += ;
        numbers.push(*num);  // 编译错误!
    }
}

编译器错误

代码语言:javascript
复制
error[E0502]: cannot borrow `numbers` as mutable because it is also borrowed as immutable
 --> src/main.rs:6:9
  |
4 |     for num in numbers.iter_mut() {
  |                ------------------
  |                |
  |                immutable borrow occurs here
  |                immutable borrow later used here
5 |         *num += 1;
6 |         numbers.push(*num);
  |         ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

人话翻译:你正在遍历 numbers,同时又想修改它。Rust 不允许这样做,会出问题的!

修复

代码语言:javascript
复制
// ✅ 正确:先收集要添加的元素
let mut numbers = vec![, , , , ];
let to_add: Vec<i32> = numbers.iter().map(|&n| n + ).collect();
numbers.extend(to_add);

🎯 实战案例

案例 1:猜数字游戏核心逻辑

代码语言:javascript
复制
use std::cmp::Ordering;

fn main() {
    let secret_number = ;
    let mut attempts = ;
    let max_attempts = ;
    
    // 使用 loop 无限循环,直到猜对或次数用完
    loop {
        attempts += ;
        
        // 检查是否超过最大尝试次数
        if attempts > max_attempts {
            println!("游戏结束!你输了。正确答案是:{}", secret_number);
            break;
        }
        
        // 模拟用户输入(实际游戏中用 input 获取)
        let guess =  + attempts * ;
        println!("第 {} 次猜测:{}", attempts, guess);
        
        // 使用 match 比较大小
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("太小了!"),
            Ordering::Greater => println!("太大了!"),
            Ordering::Equal => {
                println!("🎉 恭喜你猜对了!用了 {} 次", attempts);
                break;
            }
        }
    }
}

案例 2:处理可选配置

代码语言:javascript
复制
fn main() {
    // 模拟从配置文件读取
    let config: Option<String> = None;
    
    // 使用 if let 处理可选值
    if let Some(value) = config {
        println!("使用配置:{}", value);
    } else {
        println!("使用默认配置");
    }
    
    // 链式处理多个可选值
    let host: Option<String> = Some("localhost".to_string());
    let port: Option<u16> = Some();
    
    if let (Some(h), Some(p)) = (host, port) {
        println!("服务器地址:{}:{}", h, p);
    } else {
        println!("配置不完整,使用默认值");
    }
}

案例 3:斐波那契数列

代码语言:javascript
复制
fn main() {
    let n = ;
    let mut a = ;
    let mut b = ;
    
    println!("斐波那契数列前 {} 项:", n);
    
    // 使用 for 循环生成数列
    for i in ..n {
        if i ==  {
            print!("{} ", a);
        } else if i ==  {
            print!("{} ", b);
        } else {
            let next = a + b;
            print!("{} ", next);
            a = b;
            b = next;
        }
    }
    println!();
}

📝 最佳实践

1. 优先使用 for 循环

代码语言:javascript
复制
// ❌ 不推荐:while 循环需要手动管理索引
let mut i = ;
while i < arr.len() {
    println!("{}", arr[i]);
    i += ;
}

// ✅ 推荐:for 循环更简洁安全
for item in arr.iter() {
    println!("{}", item);
}

// ✅ 需要索引时用 enumerate()
for (index, item) in arr.iter().enumerate() {
    println!("arr[{}] = {}", index, item);
}

2. 使用 if let 简化 match

代码语言:javascript
复制
// ❌ 冗长:只关心一种情况却写完整 match
match option {
    Some(value) => println!("{}", value),
    None => (),
}

// ✅ 简洁:if let 只关心匹配成功
if let Some(value) = option {
    println!("{}", value);
}

3. 利用 if 表达式返回值

代码语言:javascript
复制
// ❌ 不推荐:先声明变量再赋值
let description;
if number >  {
    description = "正数";
} else {
    description = "非正数";
}

// ✅ 推荐:if 表达式直接返回值
let description = if number >  {
    "正数"
} else {
    "非正数"
};

4. 使用范围语法简化计数

代码语言:javascript
复制
// ❌ 冗长
let mut i = ;
while i <  {
    // ...
    i += ;
}

// ✅ 简洁
for i in .. {
    // ...
}

🧠 思维导图

03-Rust流程控制
03-Rust流程控制

📝 小结

金句时间

  1. Rust 的 if 是表达式,不是语句 — 它可以返回值,让代码更简洁
  2. for 循环是王道 — 比 while 更安全,比 loop 更常用
  3. if let 是 match 的简洁版 — 只关心匹配成功时使用
  4. loop 可以 break 返回值 — 这是 Rust 独有的骚操作
  5. 范围语法 1..4 不包含 4 — 记住这个"左闭右开"的规则

下篇预告

学会了流程控制,接下来咱们要聊聊函数!函数是代码的基本构建块,但 Rust 的函数有些"奇葩"规则:

  • 为什么参数要声明类型?
  • 返回值最后的分号为什么不能加?
  • 什么是 shadowing?它和可变变量有什么区别?

敬请期待第 04 篇:《函数基础》!


🔗 参考资料

  • Rust Book - 控制流
  • Rust By Example - if let
  • Rust By Example - loop
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Larry的Hub 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Rust 教程 - 流程控制
    • 🎬 引入
    • 📌 核心概念
      • 条件判断:if/else
      • 循环三剑客
      • if let:简洁版条件判断
    • 💻 代码示例
      • 1. if/else 基础用法
      • 2. if 作为表达式(重点!)
      • 3. if let 简洁写法
      • 4. loop 无限循环
      • 5. while 条件循环
      • 6. for 迭代循环(最常用!)
      • 7. 循环标签(高级用法)
    • 🐛 常见坑点
      • 坑点 1:忘记返回值类型一致
      • 坑点 2:忘记加分号
      • 坑点 3:while 循环条件错误
      • 坑点 4:for 循环中修改集合
    • 🎯 实战案例
      • 案例 1:猜数字游戏核心逻辑
      • 案例 2:处理可选配置
      • 案例 3:斐波那契数列
    • 📝 最佳实践
      • 1. 优先使用 for 循环
      • 2. 使用 if let 简化 match
      • 3. 利用 if 表达式返回值
      • 4. 使用范围语法简化计数
    • 🧠 思维导图
    • 📝 小结
    • 🔗 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档