在Rust中,变量使用let关键字声明:
let x = 5;
默认情况下,Rust中的变量是不可变的(immutable)。
要创建可变变量,使用mut关键字:
let mut y = 5;
y = 6; // 这是允许的
Rust允许声明同名的新变量,新变量会遮蔽旧变量:
let x = 5;
let x = x + 1; // 新的x遮蔽了旧的x
Rust有几种基本类型:
let i: i32 = 42;
let f: f64 = 3.14;
let b: bool = true;
let c: char = 'z';
let tup: (i32, f64, u8) = (500, 6.4, 1);
let arr: [i32; 5] = [1, 2, 3, 4, 5];
Rust有两种主要的字符串类型:
String: 可增长的字符串 &str: 字符串切片
let s: String = String::from("hello");
let str_slice: &str = "world";
常量使用const关键字声明,必须指定类型,且只能设置为常量表达式:
const MAX_POINTS: u32 = 100_000;
静态变量有固定的内存地址,整个程序运行期间都存在 静态变量使用static关键字声明:
static LANGUAGE: &str = "Rust";
注意:可变静态变量是可能的,但由于可能导致数据竞争,它们被认为是不安全的,需要在unsafe块中进行。
static mut COUNTER: u32 = 0;
fn main() {
unsafe {
COUNTER += 1;
println!("Counter: {}", COUNTER);
}
}
生命周期是Rust中的一个重要概念,它确保引用的有效性:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
变量的作用域通常限定在它被创建的块内:
{
let x = 5;
// x 只在这个块内有效
}
// 这里 x 无效
Rust通过所有权系统管理内存:
let s1 = String::from("hello");
let s2 = s1; // s1的所有权移动到s2
// println!("{}", s1); // 这会导致编译错误
借用允许在不获取所有权的情况下使用值:
fn calculate_length(s: &String) -> usize {
s.len()
}
let s1 = String::from("hello");
let len = calculate_length(&s1);
注意:在同一作用域内,要么只能有一个可变引用,要么可以有任意数量的不可变引用。
切片允许引用集合中的一部分连续元素:
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
在Rust中,全局变量的处理比较特殊,主要有以下几种方式:
const MAX_HEALTH: u32 = 100;
fn main() {
println!("Max health is: {}", MAX_HEALTH);
}
static LANGUAGE: &str = "Rust";
fn main() {
println!("Language: {}", LANGUAGE);
}
对于需要在多线程环境中安全使用的全局变量,可以使用std::sync模块中的类型:
use std::sync::Mutex;
use lazy_static::lazy_static;
lazy_static! {
static ref ARRAY: Mutex<Vec<u32>> = Mutex::new(vec![]);
}
fn main() {
ARRAY.lock().unwrap().push(1);
println!("Array: {:?}", ARRAY.lock().unwrap());
}
这里使用了lazy_static宏来创建一个线程安全的全局变量。
一些第三方crate提供了更方便的全局变量实现方式,例如once_cell:
use once_cell::sync::Lazy;
static HASHMAP: Lazy<std::collections::HashMap<i32, String>> = Lazy::new(|| {
let mut m = std::collections::HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
m
});
fn main() {
println!("Entry 74: {:?}", HASHMAP.get(&74));
}