跳转到内容

Rust 变量

变量(variable)就是你给一个值起的名字,方便以后使用。可以把它想象成一个贴了标签的盒子:你把东西放进盒子,在上面写个名字,之后就用这个名字来指代它,不必到处重复写那个值。

在 Rust 里,用 let 关键字创建变量:

fn main() {
let age = 30;
println!("我今年 {age} 岁");
}

输出:

我今年 30 岁
▶ 动手试一试

把这一行拆开来看:

  • let:告诉 Rust“我要创建一个新变量”。
  • age:我们起的名字。
  • =:把右边的值赋给左边的名字。
  • 30:要存的值。

println! 里的 {age} 会打印出这个变量的值。这叫作字符串插值(string interpolation):Rust 会把 {age} 替换成 age 里存的值。

Rust 里的每个值都有一个类型(整数、文字、true/false 等等)。你可能以为得自己声明类型,但通常不用:Rust 会看着值自己推断出来。这叫作类型推断(type inference)。

fn main() {
let score = 95; // Rust 推断出这是整数
let name = "Ferris"; // Rust 推断出这是文字
let is_active = true; // Rust 推断出这是布尔值
println!("{name}:{score} 分,在线 = {is_active}");
}

输出:

Ferris:95 分,在线 = true
▶ 动手试一试

如果想写得明确一些,可以在冒号后面写上类型:

let score: i32 = 95; // i32 = 32 位整数

从其他语言转过来的人常常会被这一点吓一跳:在 Rust 里,变量一旦赋值,默认就不能再改。“不可变”(immutable)的意思就是不能被修改。

下面这段代码无法编译:

fn main() {
let count = 1;
count = 2; // ❌ 错误:不能对不可变变量赋值两次
println!("{count}");
}

编译器会用一条清楚的信息拦住你:

error[E0384]: cannot assign twice to immutable variable `count`

意思是:不能对不可变变量 count 赋值两次。为什么一门语言要故意这样设计?因为很多 bug 都来自值在你没想到的时候被改掉了。除非你主动要求可以修改,否则一律不许改,这样 Rust 让你的代码更容易预测。这是一个特性,而不是限制。

当你确实需要修改某个值时,加上 mut 关键字(mutable 的缩写,意思是“可变的”):

fn main() {
let mut count = 1;
println!("修改前:{count}");
count = 2; // ✅ 现在可以了,因为有 `mut`
println!("修改后:{count}");
}

输出:

修改前:1
修改后:2
▶ 动手试一试

Rust 允许你用和旧变量相同的名字声明一个新变量。这叫作遮蔽(shadowing):新变量把旧变量“挡住”了:

fn main() {
let x = 5;
let x = x + 1; // 一个新的 x,基于旧的 x -> 6
let x = x * 2; // 又一个新的 x -> 12
println!("x 是 {x}");
}

输出:

x 是 12
▶ 动手试一试

这看起来和 mut 很像,但其实不一样:

  • mut 修改的是同一个变量的值。
  • 遮蔽创建的是一个全新的变量,只是碰巧用了同一个名字,而且它甚至可以是不同的类型。

想对一个值做转换、但又想继续用同一个名字时,遮蔽就很方便:

fn main() {
let spaces = " "; // 文字
let spaces = spaces.len(); // 现在是一个数字(有几个空格)
println!("空格的个数:{spaces}");
}

输出:

空格的个数:3
▶ 动手试一试

常量(constant)是一个永远不会改变、在编译时就确定下来的值。声明常量用 const 而不是 let,而且必须写上类型:

const MAX_SCORE: u32 = 100;
fn main() {
println!("最高分是 {MAX_SCORE}");
}

输出:

最高分是 100
▶ 动手试一试

按照惯例,常量名用 UPPER_SNAKE_CASE(全大写加下划线)书写。下面是常量和普通变量的对比:

let 变量 const 常量
能修改吗? 只有加了 mut 才能 永远不能
必须写类型吗? 可选(会自动推断) 必须
命名风格 snake_case UPPER_SNAKE_CASE
能写在哪里 函数内部 任何地方,函数外面也可以

真正固定不变的值就用常量,比如一分钟有多少秒,或者某个上限。

  • 使用 snake_case:小写单词之间用下划线连接,比如 user_name、total_price。
  • 名字可以包含字母、数字和下划线,但不能以数字开头。
  • 起一个能说明含义的名字:age 比 a 好。

创建一个变量 level,初始值为 1。打印它,然后把它加 1,重复两次,每次修改后都打印一次,最终得到 等级 1、等级 2、等级 3。提示:会改变的值需要 mut,level = level + 1; 会让它加一。

查看答案
fn main() {
let mut level = 1;
println!("等级 {level}");
level = level + 1;
println!("等级 {level}");
level = level + 1;
println!("等级 {level}");
}

输出:

等级 1
等级 2
等级 3
▶ 动手试一试

声明一个常量 SECONDS_PER_MINUTE,值为 60。先写 let time = 5;(单位是分钟),然后遮蔽 time,让它存放以秒为单位的同一段时长,并打印 也就是 300 秒。提示:新的 time 可以由旧的算出来:let time = time * ...;。

查看答案
const SECONDS_PER_MINUTE: u32 = 60;
fn main() {
let time = 5; // 分钟
let time = time * SECONDS_PER_MINUTE; // 一个新的 `time`,现在单位是秒
println!("也就是 {time} 秒");
}

输出:

也就是 300 秒
▶ 动手试一试

不需要 mut:第二个 let 创建了一个全新的变量,只是沿用了原来的名字。Rust 还会推断出这里的 time 是 u32,因为它和 u32 类型的常量相乘。

  • 用 let 创建变量;Rust 通常会帮你推断类型。
  • 变量默认不可变,加上 mut 才能修改。
  • 遮蔽是用 let 重新声明同一个名字,创建一个新变量(类型也可以变)。
  • 常量(const)永远不变,必须写类型,命名用 UPPER_SNAKE_CASE。

小测验

1. 在 Rust 里,默认情况下能给 let 变量重新赋值吗?

2. Rust 中的遮蔽(shadowing)是什么?

3. 根据本页内容,Rust 变量用哪种命名风格?

得分: 0 / 3