Rust 学习

基础

变量

Copy
let a = 10; // a不可变
let mut a = 10 // a可变

Rust 在变量离开作用域后，就自动释放内存，Rust 在结尾的 } 处自动调用 drop

基本类型

2.1 数值类型

语句：一个具体的操作，没有返回值

表达式：表达式总要返回值

Copy
fn add_with_extra(x: i32, y: i32) -> i32 {
let x = x + 1; // 语句
let y = y + 5; // 语句
x + y // 表达式
}

2.2 字符、布尔、单元类型

String 类型：动态字符串类型，分配在堆上

Copy
let mut s = String::from("hello");
s.push_str(", world!") //在字符串追加字面值

Rust 中字符是 Unicode 类型，因此每个字符占据 4 个字节

字符串是 UTF-8 编码，字符串中的字符所占的字节数是变化的 (1-4)

追加（Push）

Copy
let mut s = String::from("Hello ")
s.push_str("rust")
s.push('!')

push ()：追加字符

push_str ()：追加字符串

两个方法都是在原有的字符串上追加，并不会返回新的字符串，所以该字符串必须是可变的，由 mut 关键字修饰

插入（Insert）

Copy
let mut s = String::from("Hello rust!")
s.insert(5, ',')
s.insert_str(6, " I like")

字符串插入操作要修改原来的字符串，所以该字符串必须是可变的，必须由 mut 关键字修饰

替换（Replace）

replace

Copy
let string_replace = String::from("I like rust")
let new_string = string_replace.replace("rust", "Rust")

replacen

Copy
let s_replace = "I like rust learn rust"
let ns_replacen = s_replace.replacen("rust", "Rust", 1)

字符串替换操作要返回一个新的字符串，而不是操作原来的字符串

replace_range：仅使用 String 类型

Copy
let mut s_replace_range = String::from("I like rust")
s_replace_range.replace_range(7..8, "R")

该方法会直接操作原来的字符串，不会返回新的字符串，必须使用 mut 关键字修饰

删除（Delete）

pop：删除并返回最后一个字符

Copy
let mut s_pop = String::from("rust pop 中文!")
let p1 = s_pop.pop()

该方法是直接操作原来的字符串，但是存在返回值，如果字符串是空，则返回 None

remove：删除并返回字符串指定位置的字符

Copy
let mut s_remove = String::from("rust remove 中文")
string_remove.remove(0)

该方法是直接操作原来的字符串，但是存在字符串

truncate：删除字符串中从指定位置开始到结尾的全部字符

Copy
let mut s_truncate = String::from("测试truncate")
s_truncate.truncate(3)

该方法是操作原来字符串，无返回值

clear：清空字符串

Copy
let mut s_clear = String::from("string clear")
s_clear.clear()

该方法是直接操作原来的字符串，等价 s_clear.truncate (0)

连接(Concatenate)

使用 + 或 += 连接字符串，要求右边的参数必须为字符串的切片引用 (Slice) 类型

+ 是返回一个新的字符串，所以变量声明可以不需要 mut 关键字修饰

2.3 元组

Copy
let x : (i32, f64, u8) = (500, 6.4, 1);
let a = x.0;
let b = x.1;

2.4 结构体

初始化实例，每个字段都需要进行初始化

初始化字段顺序不需要和定义时的一致

当函数参数和结构体字段同名时，可以直接使用缩略方式初始化

user2 仅在 email 上和 user1 不同，因此只需要对 email 赋值，剩下通过..user1

Copy
fn build_user(email: String, username: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 1,
}
}

Copy
let user2 = User {
email: String::from("another@ex.com")
..user1
};

单元结构体：不关心该类型的内容，只关心它的行为

Copy
struct AlwaysEqual;
let subject = AlwaysEqual;
impl SomeTrait for AlwaysEqual {}

结构体输出打印

手动实现 Display，Debug

使用派生类

Copy
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
println!("rect1 is {:?}", rect1)

2.5 所有权和借用

Rust 中每一个值都被一个变量所拥有，改变量被称为值的所有者

一个值同时只能被一个变量所拥有，或者说一个值只能拥有一个所有者

当所有者 (变量) 离开作用域范围时，这个值将被丢弃，Rust 会自动调用 drop 函数并清理变量的堆内存

Copy
let s1 = String::from("hello");
let s2 = s1;

println!("{}, world!", s1)

s1 被赋予 s2 后，Rust 认为 s1 不再有效，因此也无需在 s1 离开作用域后 drop 任何东西，这就是把所有权 s1 转移给了 s2，s1 在被赋予 s2 后马上失效了，Rust 禁止使用无效的引用

Copy
let x = 5;
let y = x;

首先将 5 绑定到变量 x，接着拷贝 x 的值赋给 y，最终 x 和 y 都等于 5，整数是 Rust 基本数据类型，是固定大小的简单值，因此这两个值都是通过自动拷贝的方式来赋值的，都被存在栈中，无需堆上分配内存

2.6 引用和借用

获取变量的引用，称之为借用

不可变引用

Copy
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()
}

可变引用

Copy
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}

不可变引用允许同时存在多个

可变引用同时只能存在一个

可变引用和不可变引用不能同时存在