rust_learn

rust学习笔记

学习网站:

官方文档:Rust 程序设计语言 - Rust 程序设计语言 简体中文版 (kaisery.github.io),不是很推荐新手看,整个开头就直接写函数了,很多基础还要自己查。

rust圣经:关键字 - Rust语言圣经(Rust Course),推荐,讲得很不错

第一章:安装,基本命令和配置

vscode安装

安装基本工具:

安装 Rust - Rust 程序设计语言 (rust-lang.org)

选择1即可,按流程安装

ps:如果命令行 cargo 没有办法识别,配置系统的环境变量(不是用户环境变量),在path中添加

1
C:\Users\[username].cargo\bin

插件推荐:

1
2
3
4
5
rust-analyzer
Rust Syntax
crates
Rust Test Lens
Better TOML

编译

单个文件编译

1
rustc [filename]

项目建立

1
cargo new [projectname]

项目中src中的main.rs作为第一个运行的文件,其中的main函数作为第一个运行的函数

项目编译

1
2
3
4
cargo check #速度更快,检查是否可以编译
cargo build #编译
cargo run #编译并且运行
cargo bulid --release #会在target∕release下生成可执行文件,运行速度更快

配置

项目的根目录下面存在有cargo.toml

1
2
3
4
5
6
7
8
9
[package]
name = "cargo_one"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.5"

package是基本信息

dependencies是扩展包的信息

一般不含有扩展包,国内需要进行换源

window下路径为

1
C:\Users\[username]\.cargo

修改config,如果没有就建立一个,复制以下内容,更改为清华源

1
2
3
4
5
[source.crates-io]
replace-with = 'tuna'

[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"

第二章 基础学习

1. 变量

1
2
3
let a; #不可变变量
let mut a; #可变变量
let _a; #取消未使用变量警告,包括方法等

2.关键字

不能够作为变量命名的关键字如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
如下关键字目前有对应其描述的功能。

as - 强制类型转换,或use 和 extern crate包和模块引入语句中的重命名
break - 立刻退出循环
const - 定义常量或原生常量指针(constant raw pointer)
continue - 继续进入下一次循环迭代
crate - 链接外部包
dyn - 动态分发特征对象
else - 作为 if 和 if let 控制流结构的 fallback
enum - 定义一个枚举类型
extern - 链接一个外部包,或者一个宏变量(该变量定义在另外一个包中)
false - 布尔值 false
fn - 定义一个函数或 函数指针类型 (function pointer type)
for - 遍历一个迭代器或实现一个 trait 或者指定一个更高级的生命周期
if - 基于条件表达式的结果来执行相应的分支
impl - 为结构体或者特征实现具体功能
in - for 循环语法的一部分
let - 绑定一个变量
loop - 无条件循环
match - 模式匹配
mod - 定义一个模块
move - 使闭包获取其所捕获项的所有权
mut - 在引用、裸指针或模式绑定中使用,表明变量是可变的
pub - 表示结构体字段、impl 块或模块的公共可见性
ref - 通过引用绑定
return - 从函数中返回
Self - 实现特征类型的类型别名
self - 表示方法本身或当前模块
static - 表示全局变量或在整个程序执行期间保持其生命周期
struct - 定义一个结构体
super - 表示当前模块的父模块
trait - 定义一个特征
true - 布尔值 true
type - 定义一个类型别名或关联类型
unsafe - 表示不安全的代码、函数、特征或实现
use - 在当前代码范围内(模块或者花括号对)引入外部的包、模块等
where - 表示一个约束类型的从句
while - 基于一个表达式的结果判断是否继续循环

保留变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
如下关键字没有任何功能,不过由 Rust 保留以备将来的应用。

abstract
async
await
become
box
do
final
macro
override
priv
try
typeof
unsized
virtual
yield

但是可以通过前缀标识符来处理

  • Rust 中常用的标识符前缀:
    
    1. r#:用于在标识符名称中使用保留关键字。例如,r#type 表示名称为 type 的标识符。
    2. b:用于表示字节字符串(byte string)字面量,例如,b"hello" 表示字节字符串 hello。
    3. r:用于表示 raw 字符串字面量,例如,r#"hello \n world"# 表示一个包含转义字符的 raw 字符串。
    4. 0b、0o、0x:用于表示二进制、八进制和十六进制整数字面量,例如,0b101 表示二进制数 101。
    
    除了以上常用的标识符前缀之外,Rust 还支持一些其他的标识符前缀,例如:
    
    - crate:用于表示当前 crate 的根模块,例如,crate::foo 表示当前 crate 中名为 foo 的模块。
    - self:用于表示当前模块,例如,self::foo 表示当前模块中名为 foo 的标识符。
    - super:用于表示当前模块的父模块,例如,super::foo 表示当前模块的父模块中名为 foo 的标识符。
    
    1
    2
    3
    4
    5
    6
    7



    ## 3.变量类型以及绑定,解绑定义

    ### 整型

有符号类型:
i8, i16, i32, i64, i128
无符号类型:
u8, u16, u32, u64, u128

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

i8和u8只有一个字节,以此翻倍,i32有4个字节



### 字符型(char)

字符中不只是存有utf-8,还有其他的字符集,一个字符大小有4个字节



### 字符串型(&str)

大小是16个字节

use std::mem::size_of_val;
fn main() {
let s:&str = “1”;
println!(“{}”, size_of_val(&s))
}

res: 16

1
2
3
4
5
6
7
8
9



### 单位类型()

在 Rust 中,单位类型(unit type)表示为 `()`,它只有一个值,也就是空值,类似于其他编程语言中的 `void` 类型。

单位类型 `()` 可以用于表示没有返回值的函数,例如:

rustCopy codefn print_hello() -> () {
println!(“Hello, world!”);
}

1
2
3
4
5

这个函数没有返回值,因此返回类型为 `()`。另外,在 Rust 中,函数的返回值类型可以省略,编译器会自动推导出返回值类型为 `()`。

`()` 也可以作为函数参数类型,用于表示不需要参数的函数,例如:

rustCopy codefn do_something(_: ()) {
println!(“I’m doing something!”);
}

1
2
3
4
5

这个函数的参数类型为 `()`,表示它不需要任何参数。在函数体中,参数名被写作 `_`,这是一种占位符,表示这个参数不会被使用。

`()` 还可以用于元组类型中,作为元组中没有元素的占位符,例如:

let empty_tuple: () = ();

1
2
3
4
5

这个代码定义了一个空元组,它只包含一个值 `()`。空元组在 Rust 中也被称为“单元素元组”。

除此之外,`()` 还可以用于表达式中,例如:

rustCopy code
let x = 1 + (2 * ());

1
2
3
4
5
6
7
8
9

这个表达式中使用了空元组 `()`,它在这里充当了一个占位符的作用,表示这里的乘法操作不需要任何值参与,因此得到的结果仍然是 1。

总的来说,`()` 在 Rust 中有多重作用,它可以表示空值、没有返回值的函数、不需要参数的函数、空元组等等。



### 变量解构

struct Struct {
e: i32
}

fn main() {
let (a, b, c, d, e);

(a, b) = (1, 2);
// _ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有使用一个变量名而是使用了 _
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e } = Struct { e: 5 };

assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);

}

1

… 表示匹配一个序列中的所有剩余元素,例如 let [a, b, …] = [1, 2, 3, 4, 5] 将会把 a 和 b 分别赋值为 1 和 2,而剩余的元素 [3, 4, 5] 则会被忽略。
_ 被称为通配符(wildcard),它可以匹配任何类型的值,并且不会将匹配到的值绑定到任何变量上。因此,通配符 _ 可以用于丢弃不需要的值。
name @ pattern 表示将匹配到的值绑定到一个变量上,并且同时匹配一个模式。例如,match Some(42) { Some(n @ 1…=100) => println!(“Got a number between 1 and 100: {}”, n), _ => () } 表示如果匹配到的是 Some 枚举的值,并且这个值在 1 到 100 的范围内,则将其赋值给变量 n,并打印一条信息。在一个 match 表达式中,_ 可以被用作最后一个分支的模式,它可以匹配所有未被之前分支匹配到的情况。这个分支通常被称为“捕获所有”分支(catch-all branch)或者“默认”分支(default branch)。通常,当我们不需要对某个分支进行处理时,可以使用“捕获所有”分支来忽略它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

其中

在 Rust 中,`let (a, b, c, d, e);` 和 `let [a, b, c, d, e];` 的区别在于:

- `let (a, b, c, d, e);` 是解构元组的语法
- `let [a, b, c, d, e];` 是解构数组的语法

### 变量遮蔽

允许重复定义,相同的变量名字,不同的内存

{}会划分层次,不同层次按照就近原则在本身的层次中使用变量

fn main() {
let x = 5;
// 在main函数的作用域内对之前的x进行遮蔽
let x = x + 1;

{
    // 在当前的花括号作用域内,对之前的x进行遮蔽
    let x = x * 2;
    println!("The value of x in the inner scope is: {}", x);
}

println!("The value of x is: {}", x);

}