变量基础
> 理解 Rust 变量不可变性的默认设计,掌握 let 与 let mut 的用法及编译器错误诊断。
变量声明
let 关键字
概念名称: let 用于声明变量绑定。
语法结构:
┌──────────────────────────────────────┐
│ let 变量名: 类型 = 值; │
│ ↑ ↑ ↑ ↑ │
│ 关键字 名字 可选 初始值 │
│ 类型标注 │
│ │
│ let x = 5; → 类型推断 │
│ let x: i32 = 5; → 显式标注 │
└──────────────────────────────────────┘最简示例
rust
▶ Runfn main() {
let x = 5; // 类型推断为 i32
println!("x = {}", x);
}详细示例
rust
▶ Runfn main() {
// 声明一个变量
let x = 5;
println!("x = {}", x);
// 变量默认是不可变的(immutable)
// x = 6; // ❌ 错误:不能给不可变变量重新赋值
// 显式类型标注
let y: i32 = 10;
let z: f64 = 3.14;
}关键代码说明:
| 代码 | 含义 | 为什么这样写 |
|---|---|---|
let x = 5 | 声明不可变变量 | Rust 默认不可变,更安全 |
let x: i32 = 5 | 显式类型标注 | 当类型推断不确定时使用 |
// x = 6 | 重新赋值被禁止 | 编译器阻止意外修改 |
变量命名规则
rust
▶ Runfn main() {
// 推荐使用 snake_case(蛇形命名法)
let my_variable = 10;
let count = 20;
// 可以使用下划线开头(表示暂未使用)
let _unused = 5;
// 可以覆盖外部变量(shadowing)
let x = 5;
let x = 10; // 这是允许的
println!("x = {}", x); // 输出 10
}可变性
mut 关键字
概念名称: mut 使变量可变。
语法结构:
┌──────────────────────────────────────┐
│ let mut 变量名 = 值; │
│ ↑ │
│ 可变标记 │
│ │
│ let x = 5; → 不可变(默认) │
│ let mut x = 5; → 可变 │
└──────────────────────────────────────┘最简示例
rust
▶ Runfn main() {
let mut x = 5;
x = 10; // ✅ 正确:可变变量可以重新赋值
println!("x = {}", x);
}详细示例
rust
▶ Runfn main() {
// 使用 mut 声明可变变量
let mut y = 5;
println!("y = {}", y);
y = 10; // ✅ 正确:y 是可变的
println!("y = {}", y);
// 不可变 vs 可变
let a = 5; // 不可变
let mut b = 5; // 可变
// a = 6; // ❌ 错误
b = 10; // ✅ 正确
}为什么默认不可变
┌─────────────────────────────────────────────────────┐
│ 为什么变量默认不可变? │
├─────────────────────────────────────────────────────┤
│ │
│ 1. 安全性 │
│ • 防止意外修改 │
│ • 减少 bug │
│ │
│ 2. 并发安全 │
│ • 不可变数据天然线程安全 │
│ • 编译器可以做得更好优化 │
│ │
│ 3. 代码可读性 │
│ • reader 知道值不会改变 │
│ • 更容易推理代码行为 │
│ │
│ Rust 哲学:让正确的事情变得容易 │
│ │
└───────────────────────────────────────┘语言对比:变量可变性
Rust vs 其他语言
┌─────────────────────────────────────────────────────┐
│ 变量可变性对比 │
├─────────────────────────────────────────────────────┤
│ │
│ Java/C++: │
│ ├── int x = 5; // 默认可变 │
│ ├── x = 10; // ✅ 允许 │
│ ├── final int y = 5; // 需要显式标记不可变 │
│ └── 设计:可变是默认,不可变需额外声明 │
│ │
│ Python: │
│ ├── x = 5 // 可变 │
│ ├── x = 10 // ✅ 允许 │
│ ├── 无不可变变量语法 │
│ └── 设计:全部可变 │
│ │
│ Rust: │
│ ├── let x = 5; // 默认不可变 │
│ ├── x = 10; // ❌ 编译错误 │
│ ├── let mut y = 5; // 需要显式标记可变 │
│ ├── y = 10; // ✅ 允许 │
│ └── 设计:不可变是默认,可变需额外声明 │
│ │
│ 对比结论: │
│ ├── Java/C++:安全需主动追求 │
│ ├── Python:安全靠自觉 │
│ ├── Rust:安全是默认 │
│ │
└─────────────────────────────────────────────────────┘实际代码对比
rust
▶ Run// Rust:默认安全
fn main() {
let config = load_config(); // 不可变
// config = new_config(); // ❌ 编译器阻止修改
let mut counter = 0; // 显式声明需要修改
counter += 1; // ✅ 允许
}java
// Java:需要主动保护
public class Example {
void run() {
int config = loadConfig(); // 可被意外修改
config = newConfig(); // ✅ 允许(可能是 bug)
final int safeConfig = loadConfig(); // 需要显式 final
// safeConfig = newConfig(); // ❌ 编译错误
}
}常见错误诊断
错误 1:修改不可变变量
错误代码
rust
▶ Runfn main() {
let x = 5;
x = 10; // 尝试修改不可变变量
}编译器错误
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:3:5
|
2 | let x = 5;
| - first assignment to `x`
3 | x = 10;
| ^^^^^^ cannot assign twice to immutable variable
|
help: make this binding mutable
|
2 | let mut x = 5;
| +++解读错误信息
┌─────────────────────────────────────────────────────┐
│ 错误信息解读 │
├─────────────────────────────────────────────────────┤
│ │
│ error[E0384]: cannot assign twice to immutable │
│ variable `x` │
│ │ │
│ │ 错误码 E0384 = "不能给不可变变量赋值两次" │
│ │ x 是不可变的,不能再次赋值 │
│ │
│ first assignment to `x` │
│ │ │
│ │ 说明:第一次赋值位置(let x = 5) │
│ │
│ cannot assign twice to immutable variable │
│ │ │
│ │ 说明:尝试第二次赋值 │
│ │ 原因:变量不可变 │
│ │
│ help: make this binding mutable │
│ │ │
│ │ 建议:添加 mut 使变量可变 │
│ │ 解决方案:let mut x = 5; │
│ │
│ 关键:编译器告诉你原因和解决方案 │
│ │
└─────────────────────────────────────────────────────┘修复方案
rust
▶ Run// 方案 1:添加 mut(如果确实需要修改)
fn main() {
let mut x = 5; // 显式声明可变
x = 10; // ✅ 正确
}
// 方案 2:保持不可变(如果不需要修改)
fn main() {
let x = 5;
let x = 10; // 使用变量遮蔽(shadowing)
println!("{}", x);
}错误 2:未初始化变量
错误代码
rust
▶ Runfn main() {
let x: i32;
println!("{}", x); // 使用未初始化变量
}编译器错误
error[E0381]: used assignment is required but `x` is not assigned
--> src/main.rs:3:20
|
2 | let x: i32;
| - help: consider assigning a value: `let x: i32 = <value>;`
3 | println!("{}", x);
| ^ used assignment is required but `x` is not assigned解读与修复
错误码 E0381:使用了未赋值的变量
修复:
├── 方案 1:初始化变量
│ let x: i32 = 0;
│
├── 方案 2:使用类型推断(自动推断为 0)
│ let x = 0;错误 3:类型不匹配
错误代码
rust
▶ Runfn main() {
let x: i32 = "hello";
}编译器错误
error[E0308]: mismatched types
--> src/main.rs:2:18
|
2 | let x: i32 = "hello";
| ^^^^^^^ expected `i32`, found `&str`
|
= note: expected type `i32`
found reference `&str`解读与修复
错误码 E0308:类型不匹配
原因:
├── 声明类型:i32(整数)
├── 实际类型:&str(字符串)
├── 类型不兼容
修复:
├── 方案 1:修改值类型
│ let x: i32 = 42;
│
├── 方案 2:修改声明类型
│ let x: &str = "hello";错误诊断速查
| 错误码 | 错误类型 | 原因 | 快速解决 |
|---|---|---|---|
| E0384 | 修改不可变变量 | 尝试给 let 变量赋值两次 | 添加 mut |
| E0381 | 未初始化变量 | 使用未赋值的变量 | 初始化变量 |
| E0308 | 类型不匹配 | 值与声明类型不符 | 修正类型 |
小结
本章核心:
let声明变量,默认不可变let mut声明可变变量- Rust 默认不可变,主动追求安全
- 编译器错误是最好的学习线索
练习题
详见:练习题