Rust 学习#
基础#
-
变量#
let a = 10; // a不可变 let mut a = 10 // a可变
Rust 在变量离开作用域后,就自动释放内存,Rust 在结尾的 } 处自动调用 drop
-
基本类型#
2.1 数值类型#
语句:一个具体的操作,没有返回值
表达式:表达式总要返回值
fn add_with_extra(x: i32, y: i32) -> i32 { let x = x + 1; // 语句 let y = y + 5; // 语句 x + y // 表达式 }
2.2 字符、布尔、单元类型#
String 类型:动态字符串类型,分配在堆上
let mut s = String::from("hello"); s.push_str(", world!") //在字符串追加字面值
Rust 中字符是 Unicode 类型,因此每个字符占据 4 个字节
字符串是 UTF-8 编码,字符串中的字符所占的字节数是变化的 (1-4)
-
追加(Push)
let mut s = String::from("Hello ") s.push_str("rust") s.push('!')
push ():追加字符
push_str ():追加字符串
两个方法都是在原有的字符串上追加,并不会返回新的字符串,所以该字符串必须是可变的,由 mut 关键字修饰
-
插入(Insert)
let mut s = String::from("Hello rust!") s.insert(5, ',') s.insert_str(6, " I like")
字符串插入操作要修改原来的字符串,所以该字符串必须是可变的,必须由 mut 关键字修饰
-
替换(Replace)
replace
let string_replace = String::from("I like rust") let new_string = string_replace.replace("rust", "Rust")
replacen
let s_replace = "I like rust learn rust" let ns_replacen = s_replace.replacen("rust", "Rust", 1)
字符串替换操作要返回一个新的字符串,而不是操作原来的字符串
replace_range:仅使用 String 类型
let mut s_replace_range = String::from("I like rust") s_replace_range.replace_range(7..8, "R")
该方法会直接操作原来的字符串,不会返回新的字符串,必须使用 mut 关键字修饰
-
删除(Delete)
pop:删除并返回最后一个字符
let mut s_pop = String::from("rust pop 中文!") let p1 = s_pop.pop()
该方法是直接操作原来的字符串,但是存在返回值,如果字符串是空,则返回 None
remove:删除并返回字符串指定位置的字符
let mut s_remove = String::from("rust remove 中文") string_remove.remove(0)
该方法是直接操作原来的字符串,但是存在字符串
truncate:删除字符串中从指定位置开始到结尾的全部字符
let mut s_truncate = String::from("测试truncate") s_truncate.truncate(3)
该方法是操作原来字符串,无返回值
clear:清空字符串
let mut s_clear = String::from("string clear") s_clear.clear()
该方法是直接操作原来的字符串,等价 s_clear.truncate (0)
-
连接(Concatenate)
使用 + 或 += 连接字符串,要求右边的参数必须为字符串的切片引用 (Slice) 类型
+ 是返回一个新的字符串,所以变量声明可以不需要 mut 关键字修饰
2.3 元组#
let x : (i32, f64, u8) = (500, 6.4, 1); let a = x.0; let b = x.1;
2.4 结构体#
- 初始化实例,每个字段都需要进行初始化
- 初始化字段顺序不需要和定义时的一致
- 当函数参数和结构体字段同名时,可以直接使用缩略方式初始化
- user2 仅在 email 上和 user1 不同,因此只需要对 email 赋值,剩下通过..user1
fn build_user(email: String, username: String) -> User { User { email, username, active: true, sign_in_count: 1, } }
let user2 = User { email: String::from("[email protected]") ..user1 };
单元结构体:不关心该类型的内容,只关心它的行为
struct AlwaysEqual; let subject = AlwaysEqual; impl SomeTrait for AlwaysEqual {}
结构体输出打印
- 手动实现 Display,Debug
- 使用派生类
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } println!("rect1 is {:?}", rect1)
2.5 所有权和借用#
- Rust 中每一个值都被一个变量所拥有,改变量被称为值的所有者
- 一个值同时只能被一个变量所拥有,或者说一个值只能拥有一个所有者
- 当所有者 (变量) 离开作用域范围时,这个值将被丢弃,Rust 会自动调用 drop 函数并清理变量的堆内存
let s1 = String::from("hello"); let s2 = s1; println!("{}, world!", s1)
s1 被赋予 s2 后,Rust 认为 s1 不再有效,因此也无需在 s1 离开作用域后 drop 任何东西,这就是把所有权 s1 转移给了 s2,s1 在被赋予 s2 后马上失效了,Rust 禁止使用无效的引用
let x = 5; let y = x;
首先将 5 绑定到变量 x,接着拷贝 x 的值赋给 y,最终 x 和 y 都等于 5,整数是 Rust 基本数据类型,是固定大小的简单值,因此这两个值都是通过自动拷贝的方式来赋值的,都被存在栈中,无需堆上分配内存
2.6 引用和借用#
获取变量的引用,称之为借用
-
不可变引用
fn main() { let s1 = String::from("hello"); let len = calculate_len(&s1); println!("the len of '{}' is {}.", s1, len); } fn calculate_len(s: &String) -> usize { s.len() }
-
可变引用
fn main() { let mut s = String::from("hello"); change(&mut s); } fn change(some_string: &mut String) { some_string.push_str(", world"); }
- 不可变引用允许同时存在多个
- 可变引用同时只能存在一个
- 可变引用和不可变引用不能同时存在
-