# rust-learn **Repository Path**: 4my/rust-learn ## Basic Information - **Project Name**: rust-learn - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-06-16 - **Last Updated**: 2024-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Rust 笔记 [Rust 程序设计语言](https://rustwiki.org/zh-CN/book/title-page.html) ## 变量与可变性 ### 常量与变量 - 变量默认不可变 - 添加 `mut` 关键字使其可变 - 常量使用 `const` 关键字 - 常量默认不可变且总是不可变 - 常量必须声明类型 - 常量只能设置为常量表达式,而不能是在运行时计算出的值 ### 变量遮蔽 - 可以定义一个与之前同名的变量 - 计算完变量仍然不可变 - 可以改变变量类型 ### 数据类型 #### 标量类型 - 整型 - 浮点型 - 布尔 - 字符 #### 复合类型 - 元组() - 每个元素的类型可以不同 - 数组[] - 每个元素的类型必须相同 ### 函数 - 函数签名必须声明每个参数的类型 - 函数的返回值用`->`表示 ### 语句和表达式 - 语句:执行一系列操作但没有返回值 - 表达式:执行操作后有返回值 ### 控制流 - 条件 - `if`条件的值必须为`bool`类型 - 循环 - `loop`重复执行代码,配合`break`从循环返回值 - `while` - `for` 遍历集合 ## 所有权 ### 规则 - 每个值都有一个所有者 - 值的任意时刻有且仅有一个所有者 - 当所有者(变量)离开作用域时,这个值将被丢弃 ### 内存释放的位置 - 离开作用域的时候,rust调用`drop`函数。 ### 变量与数据的交互方式 - 移动,即浅拷贝,rust默认浅拷贝 - 克隆,即深拷贝,会拷贝栈和堆的数据 - 如果已知大小类型的值会存储在栈上,没有深浅拷贝的概念。 - Copy trait:一个类型实现该trait,一个旧的变量赋值给新的变量后仍然可以使用。 - Drop trait:实现了该trait的类型无法实现Copy trait ### 函数 - 参数 - 返回值 ### 引用和借用 - 像一个指针,是一个地址,指向堆中的内容,使用`&`符号表示 - 引用确保指向一个特定类型的有效值 - 创建一个引用的行为称为借用 - 借用默认不可变 - 可变引用:`&mut` - 不能同一时间(在一个作用域内)对一个变量创建多个可变引用 - 不能同一时间(在一个作用域内)对一个变量创建不可变和可变引用 - 可以同一时间(在一个作用域内)对一个变量多个不可变引用 - 垂悬引用 - 即引用没有指向的数据 ### 引用的规则 - 在任意给定时间(同一作用域内),要么只有一个可变引用,要么只能有多个不可变引用 - 引用必须总是有效的(必须有指向的值) ### slice(切片) - 允许引用集合中一段连续的元素 - 语法如下,`let s = &str[start_index..end_index];`,start_index和end_index(不包含)中间用`..`,表示取开始到结束索引之间的元素。 - 字符串的字面值就是slice ## 结构体 ### 定义和实例化 - `struct` 关键字 - 每一部分可以是不同的类型 - 要自行命名 - 不允许结构体某个字段是可变的,只能整个结构体可变 ### impl块 - `impl` 关键字,将impl块中内容与结构体关联 - 块中可以定义结构体方法,方法的第一个参数必须有一个名为`self`的Self类型参数 - 如果不想获取所有权,只想读取数据,不想写入,则第一个参数为`&self` - 如果想改变调用方法的实例,即想写入,则第一个参数为`&mut self` - 单纯想获取所有权,则第一个参数为`self`,比较少见。 - 每个结构体允许多个impl块 ### 关联函数 - 不以self作为第一个参数 - 经常用作构造函数 - 通过`结构体::关联函数`的方式访问 ## 枚举 - 没有命名字段的元组结构体 - 通过`enum`关键字定义 - 可以定义枚举值 - 任意类型的数据都可以放入枚举成员中,包含字符串、数字类型、结构体或者另一个枚举 - 枚举中可以在`impl`块中定义方法 ### match 控制流 - `match`关键字后面可以是任何类型 - 每个分支有`模式 => 代码`,代码是表达式,每个分支用逗号隔开。 - 执行时按顺序匹配,匹配就执行分支的代码,否则进行下一个分支。 - 可以匹配枚举 - 可以匹配枚举和枚举值 - 必须匹配所有的情况,否则编译无法通过。匹配是穷尽的 ### if let - 用来处理只匹配一个模式的值,忽略其他模式 - 通过等号分割一个模式和一个表达式 ## 包、crate和模块 - crate:rust编译的最小单位 - 二进制项:包含一个main函数作为入口,被编译为可执行程序 - 库(通常指这个):没有main函数,相当于其他语言的库 - crate root 是一个源文件,用来构建crate的根模块 - 包:提供一系列功能的一个或者多个crate - 一个包对应一个cargo.toml - 包中可以包含一个或者多个库crate - 包中可以包含一个或者多个二进制crate - 模块 - 模块中代码默认私有的 - 如果要被外部使用需使用pub ## 集合 ### Vector - 新建`Vec::new()` 或者 `vec!` - 更新`vec.push()` - 读取可以通过索引语法或者get方法访问,get方法返回的是Option类型 - 丢弃Vector时会丢弃其元素 ### String - 使用String:new()初始化空字符串 - 使用字符串字面量.to_string() - 使用String::from("xxx") - 使用push添加字符 - 使用push_str添加字符串 - 字符串拼接,使用+或者使用format! - 不支持字符串索引,不同语言每个字符占用的长度不一样。 - 遍历字符串的字符,使用chars() - 遍历字符串的字节,使用bytes() ### HashMap - hashmap 是标准库中的,需手动引入 - 通过HashMap::new() 创建 - 通过.insert() 添加键值对 - 键必须相同类型,值必须相同类型 - 更新-覆盖一个值 .insert() - 更新-只有键没有对应值时才插入 entry().or_insert(); - 更新-根据旧值更新新值 entry().or_insert(); ## 错误处理 ### 处理不可恢复的错误 - `panic!`宏 ### 处理可恢复的错误 - 使用`Result`处理 - 失败时panic!的简写,unwrap() 和 expect() ### 传播错误 - `?`运算符,定义成从函数中提早返回一个值。 - 适用于Result Option,用于提早返回一个值。 ## 泛型、trait、生命周期 ### 泛型 - 函数定义中使用 - 结构体定义中使用 - 枚举类型中使用 - 方法定义中使用 ### trait - 类似于其他语言的接口 - 一个将方法签名组合起来的方法 - 使用`trait`关键字 - 一个trait中可以有多个方法 - 只有在 trait 或类型至少有一个属于当前 crate 时,我们才能对 类型实现该 trait。 - 可以有默认方法 - 可以作为参数 ### 生命周期 - 被引用对象的生命周期必须比引用对象的生命周期长 - 用`'`开头 - 通过在函数签名中指定生命周期参数时,没有改变任何传入值或返回值的生命周 期,而是指出任何不满足这个约束条件的值都将被借用检查器拒绝。 - 结构体指定生命周期,结构体实例不能比其字段中的引用存在更久。 - 生命周期省略规则: 1. 编译器为每一个引用参数都分配一个生命周期参数。 2. 如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数。 3. 如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self,那么所有输出生 命周期参数被赋予 self 的生命周期。 ## 闭包和迭代器 ### 闭包 - 语法如下 ``` let closures = |x| { x } ``` - 无需在参数和返回值标注类型。 - 闭包体只有一行时,无需`{}`。 - 闭包可以捕获其环境中的对象。 - `move` 获取环境中对象的所有权。 ### 迭代器 - `iter()` 方法 - 迭代器是惰性的,使用之前不会有效果。 ## 智能指针 - 类似指针,拥有额外的元数据 - 普通引用只借用数据 - 智能指针拥有指向的数据 - 实现了`Deref`和`Drop`trait的结构体 - `Deref`:允许智能指针当作常规引用使用 - `Drop`:离开作用域时自动清理代码 ### Box - 允许一个值放在堆上而不是栈上,留在栈上的是指向堆数据的指针。 ### Rc - 引用计数 - 只能用于单线程场景 - 通过调用`Rc::clone`增加计数 - 引用离开作用域自动减少计数