【笔记】Rust学习笔记

前言

Rust是由Mozilla主导开发的通用、编译型编程语言。设计准则为“安全、并发、实用”,支持函数式、并行式、过程式以及面向对象的程式设计风格。(维基百科

编译器

下载依赖

Linux

1
2
curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env

MacOS

直接安装
1
brew install rust
手动安装
1
2
brew install rustup-init
rustup-init
1
2
3
4
5
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

1

查看Rust版本

1
rustc --version
1
rustc -V

编译并生成可执行文件

1
rustc <file>.rs

主函数

  • Rust程序会自动导入prelude库,无需手动导入即可直接使用
main.rs
1
2
3
fn main() {
...
}

通过Cargo管理项目

查看Cargo版本

  • Cargo在Rust安装时同时安装
1
cargo --version

在当前目录初始化项目

  • 在当前目录自动创建Cargo.toml配置文件,初始化当前目录作为Cargo项目
1
cargo init

创建一个新的项目

  • 通过cargo命令创建一个新的项目

  • 自动创建Cargo.toml配置文件

  • 自动初始化一个git仓库

  • 自动创建src目录,并在src目录下创建main.rs文件

<project_name>:项目名称

1
cargo new <project_name>

项目配置文件

package:当前项目配置

name:项目名称
version:项目版本
edition:使用的Rust版本

dependencies:第三方依赖crate的配置

Cargo.toml
1
2
3
4
5
6
7
8
[package]
name = "demo"
version = "0.1.0"
edition = "2021"

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

[dependencies]

检查源码

1
cargo check

编译Cargo管理的项目并生成可执行文件

  • 第一次编译时会在项目根目录生成cargo.lock文件
  • 编译后会在target目录下生成可执行文件
1
cargo build

为发布而编译

  • 此时会对编译后的可执行文件优化,但是编译时间更慢
1
cargo build --release

编译并运行Cargo管理的项目

1
cargo run

注释

1
// 单行注释
1
/* 多行注释 */

TODO

1
todo!();

输出语句

1
println!("文本内容");

格式化输出

  • 通过{}作为占位符
1
println!("文本内容{}", 1); // "文本内容1"

输入语句

  • 返回io::Result类型的值OkErr
1
2
let mut str = String::new();
std::io::stdin().read_line(&mut str).expect("读取输入错误");

变量

  • 命名规范
    • 只能包含小写字母、大写字母、数字、下划线
    • 只能以小写字母、大写字母、下划线开头
    • 变量名区分大小写

定义不可变的变量(immutable)

  • 不可变变量定义后不能被重新赋值
1
let 变量名 = 值;
1
let 变量名: 数据类型 = 值;

定义可变的变量

1
let mut 变量名 = 值;
1
let mut 变量名: 数据类型 = 值;

可变的引用

1
&mut 变量名 = &变量名;

变量的隐藏

  • 定义同名变量,新的变量会将旧的变量隐藏,只保留最后一次定义的结果
1
2
let 变量名 = 值;
let 变量名 = 值;

隐藏变量并且改变数据类型

1
2
let 变量名: 数据类型1 = 值;
let 变量名: 数据类型2 = 值;

常量

定义常量

  • 常量名称通常是大写字母
  • 定义常量时必须指定数据类型
  • 常量不能被隐藏,也不能被重复定义
  • 常量在编译时就替换为具体的值
1
const 常量名: 数据类型 = 值;

运算符

算数运算符

  • +(正号)、-(负号)
  • +(加号)、-(减号)、*/%

关系运算符

  • ><>=<===!=

逻辑运算符

  • &&||!

赋值运算符

  • =+=-=*=/=%=
  • &=|=^=<<=>>=

按位运算符

  • &|^!<<>>

分支语句

if语句

1
2
3
if 布尔表达式 {
布尔表达式成立时执行的代码
}
1
2
3
4
5
if 布尔表达式 {
布尔表达式成立时执行的代码
} else {
布尔表达式不成立时执行的代码
}
1
2
3
4
5
6
7
if 条件表达式1 {
布尔表达式1成立时执行的代码
} else if 条件表达式2 {
布尔表达式2成立时执行的代码
} else {
以上布尔表达式都不成立时执行的代码
}
1
2
3
4
5
if 布尔表达式1 {
if 布尔表达式2 {
布尔表达式12都成立时执行的代码
}
}

match

  • Rust的match语句可以返回结果,最后一行表达式表示返回值
1
2
3
4
5
let 结果变量名 = match 变量名 {
"值1" => 变量结果为值1时返回的值,
"值2" => 变量结果为值2时返回的值,
_ => 变量结果既不为值1也不为值2时返回的值
}

循环语句

while语句

1
2
3
while 布尔表达式 {
布尔表达式成立时反复执行的代码
}

for语句

遍历有序的整数

  • 遍历[1,2)的整数
1
2
3
for i in 1..2 {
...
}
  • 遍历[1,2]的整数
1
2
3
for i in 1..=2 {
...
}

遍历可迭代对象

迭代后元素保持不变
  • 迭代后元素保持不变,可以再次遍历
1
2
3
4
let list = vec!["", ""];
for item in list.iter() {
...
}
迭代后会将元素移除
  • 迭代后元素移除,不可以再次遍历
1
2
3
4
let list = vec!["", ""];
for item in list.into_iter() {
...
}
迭代时可以修改元素值
1
2
3
4
let mut list = vec!["", ""];
for item in list.iter_mut() {
...
}

loop语句

  • 无限循环
1
2
3
loop {
反复执行的代码
}

所有权

  • Rust中在栈中存储的数据(基本类型数据)不会涉及到所有权的迁移
  • Rust中在堆中存储的数据(引用类型数据)有所有权,每个数据只能由一个变量所有,当发生转移的时候新的变量获得所有权,旧的变量失去所有权,失去所有权的变量将不能再使用这个变量

转移所有权

通过赋值转移所有权

1
2
let 变量名1:引用类型 = 值;
let 变量名2 = 变量名1;

通过函数参数的传递转移所有权

1
2
let 变量名1:引用类型 = 值;
函数名(变量名1);

借用

  • 通过使用&修饰的变量实现对所有权的借用
  • 在函数执行结束会自动归还所有权
1
2
let mut 变量名1:引用类型 = 值;
函数名(&mut 变量名1);

解构结构体

1
2
3
4
5
6
7
let 结构体变量名 = 结构体名{
属性名: 属性值
};

let 结构体名 {
属性名: 属性名
} = 结构体变量名;

只解构部分属性

..:忽略其他属性

1
2
3
4
5
6
7
8
9
let 结构体变量名 = 结构体名{
属性名1: 属性值,
属性名2: 属性值
};

let 结构体名 {
属性名1: 属性名1,
..
} = 结构体变量名;

判断是否能正常解构

1
2
3
4
5
6
7
8
9
10
let 结构体变量名 = 结构体名{
属性名1: 属性值,
属性名2: 属性值
};

if let 结构体名 {属性名: 属性名} = 结构体变量名 {
解构成功时执行的语句
} else {
解构失败时执行的语句
}
1
2
3
4
5
6
7
8
let 结构体变量名 = 结构体名{
属性名1: 属性值,
属性名2: 属性值
};

while let 结构体名 {属性名: 属性名} = 结构体变量名 {
解构成功时反复执行的语句
}

完成

参考文献

哔哩哔哩——软件工艺师
哔哩哔哩——面向加薪学习
知乎——赵东颖