变量与可变性:let与mut、常量、变量遮蔽、作用域
好,咱们今天来聊聊 Rust 里最基础、但也最容易踩坑的一个话题——变量。
说实话,我刚开始学 Rust 的时候,最不习惯的就是它的变量系统。别的语言里,变量默认就是可以改的,想怎么改就怎么改。但 Rust 偏不,它默认变量是不可变的。你可能会想:「这不找麻烦吗?」
嗯,等你看完这一章,你就会明白——这恰恰是 Rust 的聪明之处。
let 绑定:默认不可变
在 Rust 里,声明一个变量用的是 let 关键字。比如:
let x = 5;
x = 6; // 编译错误!
看到没?第二行直接报错。因为 x 默认是不可变的。你可能会觉得这很烦,但我在项目中遇到过好几次,就是因为变量被意外修改,导致 bug 查了一整天。Rust 的这个设计,说白了就是帮你提前堵住漏洞。
核心原则:能用不可变,就别用可变。这是 Rust 的哲学。
mut:让变量可变
那如果我真的需要改变一个变量的值呢?很简单,加个 mut:
let mut y = 5;
y = 6; // 没问题
println!("y = {}", y); // 输出: y = 6
mut 是 "mutable" 的缩写。我个人习惯是,只有在明确需要修改的地方才加 mut,其他地方一律不加。这样代码读起来也清晰——看到 mut,你就知道这个变量后面会变。
小技巧:如果你不确定要不要加 mut,先不加。等编译器报错了再加。Rust 的编译器提示非常友好,它会告诉你「这个变量需要 mut」。
常量:const
常量跟不可变变量有点像,但区别很大。常量用 const 声明:
const MAX_POINTS: u32 = 100_000;
注意几个关键点:
- 常量必须显式标注类型(比如上面的
u32) - 常量只能被赋值为常量表达式,不能是运行时计算的结果
- 常量在整个程序生命周期内都有效
我曾经在项目里用常量来定义配置项,比如数据库连接超时时间、最大重试次数等等。这样做的好处是,所有相关的地方都引用同一个值,改一处就全改了。
注意:常量跟 let 绑定的变量不同,常量没有「遮蔽」的概念。你在一个作用域里定义了一个常量,就不能在内部作用域里再定义一个同名的常量。
变量遮蔽:Shadowing
这个特性很有意思。Rust 允许你声明一个跟之前变量同名的新变量,这就叫「遮蔽」。
let x = 5;
let x = x + 1; // 遮蔽了之前的 x
let x = x * 2;
println!("x = {}", x); // 输出: x = 12
你想想看,这跟 mut 有什么区别?
区别大了:
mut是修改同一个变量的值,变量的类型不能变- 遮蔽是创建一个全新的变量,可以改变类型
举个例子:
let spaces = " "; // 字符串类型
let spaces = spaces.len(); // 数字类型,没问题!
如果用 mut,上面这段代码会报错,因为不能把字符串改成数字。但遮蔽可以,因为本质上你创建了一个新变量。
我个人习惯在需要「转换」变量类型的时候用遮蔽。比如从字符串解析成数字,或者从宽类型转换成窄类型。这样代码读起来很流畅——你一看就知道这个变量「变了」。
避坑指南:我曾经在循环里滥用遮蔽,结果导致变量作用域混乱,调试了半天。遮蔽虽好,但别贪杯。每个作用域里遮蔽一两次就够了,多了反而让代码难懂。
变量作用域
作用域,说白了就是变量「活着」的范围。Rust 的作用域用花括号 {} 来界定:
let x = 5; // x 从这里开始生效
{
let y = 10; // y 只在这个块里有效
println!("x = {}, y = {}", x, y);
} // y 在这里被销毁
// println!("y = {}", y); // 编译错误!y 已经不存在了
为什么会这样?因为 Rust 在变量离开作用域时,会自动调用 drop 来释放资源。这一点跟 C++ 的 RAII 很像,但 Rust 做得更彻底、更安全。
我在项目中遇到过一个问题:有个同事在函数开头声明了一大堆变量,结果后面根本用不到。这不仅浪费内存,还让代码变得难以维护。所以我的建议是:变量尽量在靠近使用的地方声明,用完就让它离开作用域。
知识体系总览
下面这张图帮你理清本章的核心逻辑:
总结一下
这一章我们聊了四个核心概念:
- let:默认不可变,安全第一
- mut:需要可变时显式声明
- const:编译期常量,全局有效
- 遮蔽:同名新变量,可改变类型
- 作用域:变量存活的范围,离开即销毁
说实话,这些概念单独看都不难。但组合起来,就能写出既安全又灵活的代码。我在实际项目中,经常用不可变变量来保证数据不被意外修改,用遮蔽来做类型转换,用作用域来控制资源的生命周期。
嗯,这一章就到这里。记住一句话:Rust 的变量系统,不是限制你,而是保护你。