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
是全局变量方便调用而不是在函数中传来传去,但 const
和 static
关键字好像都不支持。有什么好办法吗?
解决方式:
#[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
换一种方式
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) => 会更好
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
关键字不能在全局范围内使用。我们只能使用static
或const
。后者声明的是一个真正的常量,而不是一个变量。只有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 提供了一些特殊的机制来确保全局变量的安全性。
一种常用的方法是使用Mutex
或RwLock
等同步机制。
示例:
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
的锁,并将其值修改为一个包含一个 Entry
的 Vec
。需要注意的是,在使用可变全局变量时,必须使用 unsafe
关键字,最后,我们打印出了修改后的 TABLE
的值。
全局变量的使用需要特别注意并发安全性问题。由于全局变量可以在程序的任何地方使用,因此可能会引起数据竞争等问题。为了解决这些问题,Rust 提供了一些特殊的机制来确保全局变量的安全性,例如 Mutex
、RwLock
、Atomic
和 Channel
等。在使用全局变量时,我们需要根据实际情况选择合适的同步机制,以确保程序的并发安全性。
其他用法参考地址:
在 Rust 中使用全局变量