Rust 常量与静态变量详解:const 与 static 的区别

《Rust 编程实战》系列第 8 篇

在上一篇文章中,我们学习了 Rust 的基础数据类型。

现在我们已经知道如何使用 let 定义变量,例如:

rust 复制代码
let name = "Rust";

但是,并不是所有数据都会发生变化。

例如:

  • π(圆周率)

  • 一天有 24 小时

  • HTTP 默认端口 80

  • HTTPS 默认端口 443

  • 应用程序名称

  • API 版本号

这些数据通常在程序运行期间不会发生变化。

Rust 提供了两种方式来表示这类数据:

  • const(常量)

  • static(静态变量)

很多初学者容易混淆它们。

本文将详细介绍它们的区别以及实际开发中的使用场景。


什么是常量?

常量(Constant)是程序运行过程中永远不会改变的数据。

使用:

rust 复制代码
const

定义。

例如:

rust 复制代码
const PI: f64 = 3.1415926;

fn main() {
    println!("{}", PI);
}

输出:

text 复制代码
3.1415926

const 的语法

语法如下:

rust 复制代码
const 常量名: 类型 = 值;

例如:

rust 复制代码
const MAX_SIZE: usize = 1024;

需要注意:

const 必须显式指定类型。

下面这样是不允许的:

rust 复制代码
const MAX = 100;

正确写法:

rust 复制代码
const MAX: i32 = 100;

这是 constlet 的一个重要区别。


常量命名规范

Rust 社区推荐:

全部使用大写字母。

多个单词:

使用下划线连接。

例如:

rust 复制代码
const MAX_USER: usize = 100;

const API_VERSION: &str = "v1";

const APP_NAME: &str = "Rust CMS";

这样一眼就能知道:

这是常量。


const 可以定义在哪里?

可以在:

函数外:

rust 复制代码
const PI: f64 = 3.14;

fn main() {
    println!("{}", PI);
}

也可以:

函数内:

rust 复制代码
fn main() {

    const MAX: i32 = 100;

    println!("{}", MAX);

}

都合法。


const 的特点

Rust 的常量具有以下特点:

  • 必须指定类型

  • 编译时确定值

  • 不占用可变内存

  • 不允许修改

  • 可以在多个地方重复使用

例如:

rust 复制代码
const YEAR: i32 = 2026;

以后:

任何地方:

都可以使用。


const 不能修改

例如:

rust 复制代码
const MAX: i32 = 100;

fn main() {

    MAX = 200;

}

编译:

直接报错。

因为:

常量就是:

不能修改。


const 可以参与计算

例如:

rust 复制代码
const WIDTH: i32 = 100;

const HEIGHT: i32 = 50;

const AREA: i32 = WIDTH * HEIGHT;

因为:

这些计算:

编译时即可完成。


什么是静态变量?

Rust 还有另一种:

全局数据。

使用:

rust 复制代码
static

例如:

rust 复制代码
static APP_NAME: &str = "Rust Blog";

fn main() {

    println!("{}", APP_NAME);

}

输出:

text 复制代码
Rust Blog

看起来:

和:

rust 复制代码
const

很像。

其实:

它们完全不同。


static 的特点

静态变量:

整个程序运行期间:

始终存在。

也就是说:

程序启动:

创建。

程序退出:

释放。

生命周期:

整个程序。

因此:

叫:

Static。


static 的语法

语法:

rust 复制代码
static 名称: 类型 = 值;

例如:

rust 复制代码
static VERSION: &str = "1.0.0";

也必须:

指定类型。


const 与 static 的区别

这是最容易混淆的地方。

const static
编译时常量 全局变量
每次使用都会内联 只有一份数据
没有固定内存地址 有固定内存地址
生命周期不限于内存位置 生命周期贯穿整个程序
更推荐使用 使用场景较少

例如:

rust 复制代码
const MAX: i32 = 100;

编译后:

很多地方:

直接:

替换:

text 复制代码
100

不会真正创建一个全局变量。


而:

rust 复制代码
static APP: &str = "Rust";

程序运行后:

内存中:

只有一份:

APP。

所有地方:

共享。


static mut

Rust 允许:

rust 复制代码
static mut

例如:

rust 复制代码
static mut COUNT: i32 = 0;

理论上:

可以:

修改。

例如:

rust 复制代码
unsafe {

    COUNT += 1;

}

但是:

需要:

rust 复制代码
unsafe

为什么?

因为:

多个线程:

同时修改:

可能发生:

数据竞争。

因此:

Rust 不允许:

直接访问。


为什么尽量不要使用 static mut?

例如:

两个线程:

同时:

rust 复制代码
COUNT += 1;

结果:

可能:

错误。

因此:

Rust 要求:

必须:

rust 复制代码
unsafe

开发中:

几乎不会:

直接使用:

rust 复制代码
static mut

如何共享全局可变数据?

Rust 推荐:

使用:

rust 复制代码
Mutex

或者:

rust 复制代码
RwLock

例如:

rust 复制代码
static CONFIG: OnceLock<String> = OnceLock::new();

或者:

rust 复制代码
static USERS: LazyLock<Vec<String>> = LazyLock::new(|| Vec::new());

在现代 Rust 中,更推荐使用标准库提供的 OnceLockLazyLock,或者配合 MutexRwLock 实现线程安全的全局状态,而不是使用 static mut


const 的常见使用场景

例如:

HTTP 状态码:

rust 复制代码
const HTTP_OK: u16 = 200;

const HTTP_NOT_FOUND: u16 = 404;

或者:

配置:

rust 复制代码
const APP_NAME: &str = "Rust CMS";

const VERSION: &str = "1.0";

再例如:

限制:

rust 复制代码
const MAX_UPLOAD: usize = 1024 * 1024 * 10;

都非常适合。


static 的常见使用场景

例如:

程序名称:

rust 复制代码
static APP_NAME: &str = "Rust Server";

日志:

rust 复制代码
static LOGGER: Logger = ...;

全局配置:

rust 复制代码
static CONFIG: OnceLock<Config> = OnceLock::new();

缓存:

rust 复制代码
static CACHE: LazyLock<HashMap<...>> = ...;

这些对象:

整个程序:

只有:

一份。


let、const、static 对比

特性 let const static
是否可变 默认不可变,可加 mut 默认否,static mut 可变但不推荐
是否需要类型 可推导 必须指定 必须指定
生命周期 当前作用域 编译期常量 整个程序
是否有固定内存地址 通常没有(内联)
推荐用途 普通变量 常量 全局只读数据

常见错误

const 忘记写类型

错误:

rust 复制代码
const MAX = 100;

正确:

rust 复制代码
const MAX: i32 = 100;

修改 const

错误:

rust 复制代码
const PI: f64 = 3.14;

PI = 3.15;

常量:

不能修改。


滥用 static mut

例如:

rust 复制代码
static mut COUNT: i32 = 0;

虽然可以:

但是:

开发中:

几乎不用。

推荐:

使用:

rust 复制代码
Mutex

RwLock

OnceLock

LazyLock

这些更安全。


最佳实践

开发过程中建议遵循以下原则:

  • 普通变量使用 let

  • 固定不变的值使用 const

  • 全局共享且只读的数据使用 static

  • 全局可变状态优先使用 OnceLockLazyLock 配合 MutexRwLock,不要直接使用 static mut

  • 常量统一使用大写字母和下划线命名,保持代码风格一致。


本章小结

Rust 提供了三种不同的数据定义方式:

  • let:定义普通变量。

  • const:定义编译期常量。

  • static:定义程序运行期间一直存在的静态变量。

它们虽然看起来相似,但使用场景完全不同。

通过本文,你已经掌握了:

  • const 的定义和特点

  • static 的定义和特点

  • conststatic 的区别

  • 为什么不推荐使用 static mut

  • 企业项目中推荐的全局状态管理方式

  • 常见错误和最佳实践

理解这些内容后,你将在后续学习生命周期、模块系统以及多线程编程时更加得心应手。


下一篇预告

下一篇我们将学习 Rust 函数(Functions)

包括:

  • 如何定义函数

  • 函数参数

  • 返回值

  • 表达式与语句

  • 提前返回

  • 单元类型 ()

  • 函数的最佳实践

函数是 Rust 程序组织代码的基础,也是后续学习模块、Trait 和泛型的重要前提。

相关推荐
戮漠summer12 小时前
Missing Semester 计算机教育中缺失的一课 Lecture 01 Shell
开发语言·后端·scala
IT_陈寒14 小时前
Redis的KEYS命令把我搞崩溃了,改用SCAN才活过来
前端·人工智能·后端
长不胖的路人甲14 小时前
SpringCloud 服务雪崩、熔断、降级
后端·spring·spring cloud
爱折腾的小黑牛15 小时前
小程序多人协作的权限设计:三级权限的实现
后端
蓝银草同学16 小时前
Stream 实战:博客列表排序、过滤与分页(AI 辅助学习 Java 8)
java·前端·后端
小小猪的春天17 小时前
AI 编程 30 天实验复盘:效率提升 65%,线上 bug 涨到 11 个,问题出在哪
后端
爱勇宝17 小时前
3位工程师靠“删AI代码”创业,一周收费1万美元:以后最贵的能力,可能不是写代码
前端·后端·架构
不能放弃治疗18 小时前
rule 和 skill
后端