基础语法 beginner 25 分钟 更新 2026-06-15

变量、可变性与 shadowing

理解 let、mut、const 和 shadowing 的差异。

变量、可变性与 shadowing

你会学到什么

  • Rust 变量默认不可变。
  • mut 允许同一个绑定被重新赋值。
  • shadowing 会创建新的绑定,可以改变类型。

最小示例

let lessons = 1;
let lessons = lessons + 1;

let mut completed = 0;
completed += 1;

第一段代码是 shadowing:第二个 lessons 是一个新绑定。第二段代码是 mutation:completed 这个绑定本身被修改。

运行代码

cd examples
cargo run -p rt_02_variables
cargo test -p rt_02_variables

代码讲解

默认不可变让数据流更容易推理。你看到一个没有 mut 的变量,就知道它不会在同一作用域里被重新赋值。

const 用于编译期常量,必须写类型:

const TOTAL_STAGES: u32 = 16;

shadowing 适合表达“处理后的新值”,例如把输入字符串去空格后再解析为数字。

常见错误

下面的代码会报错,因为 score 没有声明为 mut

let score = 1;
score += 1;

修复方式是显式写出可变性:

let mut score = 1;
score += 1;

练习

  • 在示例中增加一个 const COURSE_NAME: &str
  • 用 shadowing 把一个字符串 "42" 解析成数字。

小结

mut 改变的是同一个绑定,shadowing 创建的是新绑定。默认不可变是 Rust 可维护性的基础。

下一步

下一章学习标量类型和复合类型。

完整示例代码

下面是 examples/02_variables/ 的完整源码。无需 clone 仓库,直接在页面上阅读、复制、对照运行。

examples/02_variables/src/main.rs
const TOTAL_STAGES: u32 = 16;

fn advance_stage(current: u32) -> u32 {
    let current = current + 1;
    current.min(TOTAL_STAGES)
}

fn completed_message(completed_examples: u32) -> String {
    format!("已完成示例: {completed_examples}")
}

fn main() {
    let current_stage = 1;
    let current_stage = advance_stage(current_stage);

    let mut completed_examples = 0;
    completed_examples += 1;

    println!("当前阶段: {current_stage}/{TOTAL_STAGES}");
    println!("{}", completed_message(completed_examples));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn stage_does_not_exceed_total() {
        assert_eq!(advance_stage(16), 16);
    }

    #[test]
    fn formats_completed_message() {
        assert_eq!(completed_message(3), "已完成示例: 3");
    }
}
examples/02_variables/Cargo.toml
[package]
name = "rt_02_variables"
version.workspace = true
edition.workspace = true
publish.workspace = true