让学习快乐起来
变量
- 变量 let 是无法改变的,值不可变,类型也不可变 ✨✨✨✨✨
let x i32 = 8; //海枯石烂 地球爆炸 都等于8
- 通过使用 mut 关键字,可以声明一个可变变量 ✨✨✨✨✨
let mut x i32 = 8;
x = 12
- 通过使用 as 关键字,可以通过旧变量生成一个新的类型的变量,但是旧的变量依然存在,类型还是无法改变,只是新创建了一个变量 ✨✨✨✨✨
let num: i32 = 42;
let num_float: f64 = num as f64; //旧的 num 依然存在
- 常量 const 永远无法改变 ✨✨✨✨✨
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
- 通过使用 let 重新声明一个原有的变量,会生成一个新的变量,旧的变量被遮蔽( `隐藏),相对于 go 语言来说,遮蔽让程序可以避免声明多余的
变量,在同一个定义域内可以多次声明同名变量。是一个非常灵活的设计。当然你不用也可以~ ✨✨✨
单数据类型
这个地方我希望介绍具体的数据类型而不仔细深究其实现,并列举一些最佳实践。
- 布尔
true, false
- 数字
i8,i32, u8, u32,f32,f64, isize(sign pointer),usize(non pointer) ✨✨✨✨✨没什么好讲
- 不可变字符串
“lucas” 字符串字面量是分配在栈中的不可变变量,就是一个 utf8 码点的 slice, [23 12 34 53 12 34],使用中都是 &str,因为只读.
- 可变字符串
使用 String::new()的关联方法,也就是 python 里面 String 类的一个静态方法,可以创建一个String,String 类型分配在堆上,因为无法预知长度.
- 字符串转换
str -> String //使用 str 内置实现的 from() into(),这是两个转换类的接口,看他们的名字你应该知道是干什么的
let lucasString:String = "lucas".into();
String -> str //使用引用符号,这很像 python!,对字符串进行切片(动词),就是一个引用.
let lucasStr:&str = &lucasString;
5.char
char占 4 个字节,可以表示任何一个 unicode,说白了就是任意一个字符
集合类型 std::collections
- 元组 tuple
元组 类比 python 里面的元组,不可变, 解构
// 基本语法
let tup: (i32, f64, u8) = (500, 6.4, 1);
let t1:i32 = tup.0;
let t2:f64 = tup.1;
// 元组的实践, 看不懂的话以后再看.就是可以 match 一个元组,从而产生 2的 n 次方种结果.比 if else 好看多了.
fn func1() -> Result<i32, &'static str> { Ok(1) }
fn func2() -> Result<i32, &'static str> { Ok(2) }
fn func3() -> Result<i32, &'static str> { Err("error") }
fn main() {
match (func1(), func2(), func3()) {
(Ok(r1), Ok(r2), Ok(r3)) => println!("All succeeded: {}, {}, {}", r1, r2, r3),
(Err(e), _, _) | (_, Err(e), _) | (_, _, Err(e)) => println!("An error occurred: {}", e),
}
}
- 数组(不可变) ✨
全世界的不可变数组都是连续内存的申请,因为长度不可变,所以分配在栈上.
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"]; //看起来不错吧,但是我肯定用枚举.
- Vec(可变)
vector,我打算也不叫切片也不叫数组了,就叫 vector,下面的Some 暂时理解就是如果存在 IF EXIST OR GET,而且很明显这种应该和 python 的 list 一样,都默认实现了迭代器__iter__().
fn main() {
let mut vec = Vec::new();
// 添加元素
vec.push(10);
vec.push(20);
vec.push(30);
// 处理不存在的索引
match vec.get(3) {
Some(value) => println!("Value at index 3: {}", value),
None => println!("Index 3 is out of bounds"),
}
// 遍历元素
for (index, value) in vec.iter().enumerate() {
println!("Element at index {}: {}", index, value);
}
// 修改元素
if let Some(value) = vec.get_mut(1) {
*value = 200;
}
// 删除元素
if let Some(removed) = vec.pop() {
println!("Removed element: {}", removed);
}
println!("Updated Vector: {:?}", vec);
}
- HashMap
为什么不叫Map呢… 所有的代码都是 GPT 生成的.
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
// 使用 entry 方法插入新值或更新现有值
map.entry("key1".to_string()).or_insert(10);
map.entry("key2".to_string()).or_insert(20);
// 处理不存在的键
match map.get("key3") {
Some(value) => println!("Value for 'key3': {}", value),
None => println!("Key 'key3' not found"),
}
// 使用 contains_key 方法检查键是否存在
if !map.contains_key("key3") {
println!("Key 'key3' does not exist in the HashMap");
}
// 遍历元素
for (key, value) in map.iter() {
println!("Key: {}, Value: {}", key, value);
}
// 使用 remove 方法删除键值对
if let Some(value) = map.remove("key1") {
println!("Removed value for 'key1': {}", value);
}
println!("Updated HashMap: {:?}", map);
}
let Some(T) 类似于 go 里面的 if v,ok := func1; ok {}
reference:https://kaisery.github.io/trpl-zh-cn/ch08-03-hash-maps.html //rust 圣经