rust如何定义全局对象变量

rust 复制代码
struct DataItem {
  lv: i32,
  rate: f32,
  fall: Option<i32>,
}

let data : Vec<DataItem> = vec![
  DataItem {
    lv: 1,
    rate: 1.0,
    fall: None,
  },
  DataItem {
    lv: 2,
    rate: 1.0,
    fall: None,
  }
];

我想让 data 是全局变量方便调用而不是在函数中传来传去,但 conststatic 关键字好像都不支持。有什么好办法吗?

解决方式:

rust 复制代码
#[derive(Debug)]
struct DataItem {
  lv: i32,
  rate: f32,
  fall: Option<i32>,
}

const  DATA:[DataItem;2]  = [
  DataItem {
    lv: 1,
    rate: 1.0,
    fall: None,
  },
  DataItem {
    lv: 2,
    rate: 1.0,
    fall: None,
  }
];


fn main() {
    let mut item = &mut DATA[0];
    item.lv = 4;
    println!("{:?}",DATA[0]);
}

遇到问题:

遇到的问题是:

let mut item = &mut DATA[0];

= note: each usage of a const item creates a new temporary

= note: the mutable reference will refer to this temporary, not the original const item`

如果使用static则不能可变引用DATA,因为DATA item is an immutable static item

换一种方式

rust 复制代码
static mut DATA:Vec<DataItem> = Vec::new();

#[derive(Debug)]
struct DataItem {
  lv: i32,
  rate: f32,
  fall: Option<i32>,
}

fn main() {
    unsafe {
     let i = DataItem {
        lv: 1,
        rate: 1.0,
        fall: None,
     };
     DATA.push(i);
     
     let i = DataItem {
        lv: 2,
        rate: 1.0,
        fall: None,
     };
     DATA.push(i);
     
     let mut i  = &mut DATA[0];
     i.lv = 3;
     println!{"{:?}",i};
     
  }
    
}
把全局变量设置为懒加载(lazy),可在多个线程访问(sync),线程安全(mutex) => 会更好
rust 复制代码
use std::sync::Mutex;
use once_cell::sync::Lazy;

#[derive(Debug)]
struct DataItem {
    lv: i32,
    rate: f32,
    fall: Option<i32>,
}

static GLOBAL_DATA: Lazy<Mutex<Vec<DataItem>>> = Lazy::new(|| {
    let mut m = Vec::new();
    m.push(
       DataItem {
        lv: 1,
        rate: 1.0,
        fall: None,
     }
    );
    m.push(
      DataItem {
        lv: 2,
        rate: 2.0,
        fall: None,
      }
     );
    Mutex::new(m)
});

fn main() {
    let mut v =  GLOBAL_DATA.lock().unwrap();
    let mut item = &mut v[0];
    item.lv = 4;
    println!("{:?}", item);
}

还有提供的解决方案:

let 关键字不能在全局范围内使用。我们只能使用staticconst 。后者声明的是一个真正的常量,而不是一个变量。只有static 给我们一个全局变量。

这背后的原因是,let 在运行时在堆栈上分配了一个变量。请注意,当在堆上分配时,这仍然是真实的,如let t = Box::new(); 。在生成的机器代码中,仍然有一个指向堆的指针,它被存储在堆上。

全局变量被存储在程序的数据段中。它们有一个固定的地址,在执行过程中不会改变。因此,代码段可以包括常数地址,并且完全不需要堆栈中的空间。

好了,我们可以理解为什么我们需要一个不同的语法。Rust作为一种现代系统编程语言,希望在内存管理方面非常明确

定义全局变量

在 Rust 中,定义全局变量需要使用static关键字。定义全局变量的方式有两种:

定义不可变的全局变量

static GLOBAL_VAR: i32 = 42;

在上述代码中,我们定义了一个名为GLOBAL_VAR的全局变量,类型为i32,初始值为42。需要注意的是,定义的全局变量必须指定类型。在定义不可变的全局变量后,我们可以在程序的任何地方读取它的值。

定义可变的全局变量

static mut GLOBAL_VAR: i32 = 42;

在上述代码中,我们使用static mut定义了一个名为GLOBAL_VAR的可变全局变量,类型为i32,初始值为42。需要注意的是,定义可变的全局变量必须使用mut关键字,并且在使用可变全局变量时需要使用unsafe关键字。

全局变量的安全性

在 Rust 中,全局变量的使用需要特别注意并发安全性问题。由于全局变量可以在程序的任何地方使用,因此可能会引起数据竞争等问题。为了解决这些问题,Rust 提供了一些特殊的机制来确保全局变量的安全性。

一种常用的方法是使用MutexRwLock等同步机制。

示例:

rust 复制代码
use std::sync::Mutex;

static mut TABLE: Mutex<Table> = Mutex::new(Table::new());

type Table = Vec<Entry>;

#[derive(Debug)]
#[allow(dead_code)]
struct Entry {
    key: i32,
    value: i32,
}

fn main() {
    let mut table = unsafe { TABLE.lock().unwrap() };
    // let mut entry = Entry { key: 1, value: 10 };
    *table = vec![Entry { key: 1, value: 10 }];
    println!("table: {:?}", table);
}

述代码演示了如何在 Rust 中定义可变的全局变量。

首先,我们使用 use 关键字导入了 std::sync::Mutex,这是 Rust 中的一种同步机制。接着,我们使用 static mut 关键字定义了一个名为 TABLE 的可变全局变量,类型为 Mutex<Table>。在 Rust 中,使用 Mutex 来保护共享数据的并发安全性是一种常用的方式。

main() 函数中,我们获取了 TABLE 的锁,并将其值修改为一个包含一个 EntryVec。需要注意的是,在使用可变全局变量时,必须使用 unsafe 关键字,最后,我们打印出了修改后的 TABLE 的值。

全局变量的使用需要特别注意并发安全性问题。由于全局变量可以在程序的任何地方使用,因此可能会引起数据竞争等问题。为了解决这些问题,Rust 提供了一些特殊的机制来确保全局变量的安全性,例如 MutexRwLockAtomicChannel 等。在使用全局变量时,我们需要根据实际情况选择合适的同步机制,以确保程序的并发安全性。

其他用法参考地址:
在 Rust 中使用全局变量

ArchGrid - 架构知识网格 - Rust惑点启示系列(七):使用全局变量和单例

相关推荐
hy____1233 分钟前
C语言:数据的存储
c语言·开发语言
prettyxian9 分钟前
【c++】vector的使用
开发语言·c++
GISer Liu31 分钟前
深入理解Transformer中的解码器原理(Decoder)与掩码机制
开发语言·人工智能·python·深度学习·机器学习·llm·transformer
TANGLONG2221 小时前
【C++】类与对象初级应用篇:打造自定义日期类与日期计算器(2w5k字长文附源码)
java·c语言·开发语言·c++·python·面试·跳槽
martian6651 小时前
第23篇:Python开发进阶:详解测试驱动开发(TDD)
开发语言·驱动开发·python·tdd
xianwu5431 小时前
反向代理模块1
开发语言·网络·数据库·c++·mysql
夏子曦1 小时前
Python+OpenCV(1)---傅里叶变换
开发语言·python·opencv
拿我格子衫来2 小时前
图形编辑器基于Paper.js教程22:在图形矢量编辑器中,实现两个元素的差集,交集,并集,切割
前端·javascript·图像处理·编辑器·图形渲染
哟哟耶耶2 小时前
css-background-color(transparent)
前端·css