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;

这是 const 与 let 的一个重要区别。


常量命名规范

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 中,更推荐使用标准库提供的 OnceLock、LazyLock,或者配合 Mutex、RwLock 实现线程安全的全局状态,而不是使用 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。

  • 全局可变状态优先使用 OnceLock、LazyLock 配合 Mutex 或 RwLock,不要直接使用 static mut。

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


本章小结

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

  • let:定义普通变量。

  • const:定义编译期常量。

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

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

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

  • const 的定义和特点

  • static 的定义和特点

  • const 与 static 的区别

  • 为什么不推荐使用 static mut

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

  • 常见错误和最佳实践

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


下一篇预告

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

包括:

  • 如何定义函数

  • 函数参数

  • 返回值

  • 表达式与语句

  • 提前返回

  • 单元类型 ()

  • 函数的最佳实践

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

相关推荐
程序员海军7 小时前
用了两年多 GPT,我最近开始换模型了,还折腾了个求职避坑 Agent
前端·人工智能·后端
码士集团小青7 小时前
SpringBoot 集成缓存性能之王 Caffeine
spring boot·后端·缓存
excel9 小时前
IndexNow:让搜索引擎更快发现网站更新的主动通知协议
前端·后端·架构
Json____9 小时前
用 FastAPI + Vue3 打造一套完整的在线考试系统:从组卷到阅卷的业务闭环实践
后端·node.js·fastapi·it学习·wwwoop.com
小灰灰搞电子10 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
专业程序开发源11 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
卷无止境11 小时前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
IT_陈寒12 小时前
JavaScript的闭包陷阱,这个坑我躺了三天才爬出来
前端·人工智能·后端
用户83562907805112 小时前
如何使用 Python 对 Excel 数据进行分组和分级显示
后端·python
vx_Biye_Design12 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express