You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust 中如何实现不同模块共同填充全局静态数组或Vec?

问题原因

你的原代码无法运行有两个核心问题:

  1. lazy_static生成的静态变量默认是不可变的,没有内部可变性支撑的前提下,无法直接调用extend修改内部的Vec
  2. 静态变量的初始化顺序是Rust未定义行为,你无法保证模块a的TEST先初始化完成,再执行模块b的扩展逻辑,很容易出现未初始化就访问的问题。

可行实现方案

方案1:手动控制初始化流程(最稳妥,无额外依赖)

Rust 1.70及以上版本可以直接用标准库的OnceLock实现,核心思路是将注册阶段和只读阶段拆分,启动阶段统一收集所有注册内容,完成后冻结为全局只读变量:

use std::sync::{OnceLock, Mutex};

// 全局只读存储,初始化完成后不可修改
static TEST: OnceLock<Vec<u32>> = OnceLock::new();
// 启动阶段的临时注册容器,仅初始化阶段使用
static TEST_REG: Mutex<Vec<u32>> = Mutex::new(Vec::new());

mod a {
    use super::*;
    pub fn init() {
        TEST_REG.lock().unwrap().extend([1, 2, 3]);
    }
}

mod b {
    use super::*;
    pub fn init() {
        TEST_REG.lock().unwrap().extend([4, 5, 6]);
    }
}

fn main() {
    // 启动阶段按顺序执行所有模块的注册逻辑
    a::init();
    b::init();
    
    // 冻结数据,后续仅支持只读访问
    TEST.set(TEST_REG.lock().unwrap().clone()).unwrap();

    // 业务逻辑只读访问
    for &val in TEST.get().unwrap() {
        println!("{}", val);
    }
}

该方案完全可控,不需要引入第三方依赖,初始化顺序可自行调整,适合对稳定性要求高的场景。

方案2:自动注册(无需手动调用初始化函数)

如果不想在main函数里逐个调用模块的初始化函数,可以用inventory库实现编译期自动收集注册项,新增模块不需要修改main的初始化逻辑:
首先添加依赖到Cargo.toml:

[dependencies]
inventory = "0.3"

代码示例:

use inventory::collect;

// 定义需要注册的项类型
#[derive(Debug, Clone, Copy)]
struct TestItem(u32);
// 声明该类型支持全局收集
collect!(TestItem);

mod a {
    use super::*;
    // 模块内直接提交注册项,不需要对外暴露初始化函数
    inventory::submit! { TestItem(1) }
    inventory::submit! { TestItem(2) }
    inventory::submit! { TestItem(3) }
}

mod b {
    use super::*;
    inventory::submit! { TestItem(4) }
    inventory::submit! { TestItem(5) }
    inventory::submit! { TestItem(6) }
}

fn main() {
    // 一次性收集所有注册项,转为只读的Vec使用
    let test: Vec<u32> = inventory::iter::<TestItem>().map(|item| item.0).collect();
    
    // 也可以存入OnceLock作为全局只读变量使用
    for &val in &test {
        println!("{}", val);
    }
}

该方案适合模块数量多、迭代频繁的场景,新增扩展模块只需要自己提交注册项即可,不需要修改上层初始化代码。

注意事项

  • 两种方案都保证了运行阶段数据只读,不会出现并发修改问题
  • 如果需要注册函数,只需要将存储的元素类型替换为函数指针或者Box<dyn Fn(...) + Sync + Send>即可,逻辑完全一致

内容的提问来源于stack exchange,提问作者glasflügel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 14:09:03