rust 相关知识
目录
1. 基本命令
1.1. rustup
# 安装 curl --proto '=https' --tlsv1.3 https://sh.rustup.rs -sSf | sh # 更新 rustup update # 卸载 rustup self uninstall # 编译 rustc main.rs
1.2. cargo
# 创建项目 cargo new project_name # 库项目 cargo new --lib lib_name # 构建 cargo build # 发布构建 cargo build --release # 运行 cargo run # 检查 cargo check # 更新 crate cargo update
2. 基本知识
2.1. 变量、数据类型
2.1.1. 变量
// 常量, 必须注明类型, 只能是常量表达式 const THREE: u32 = 3 * 3; pub fn main() { let a1 = 1; // 可变变量 let mut a2 = 2; // 隐藏前面的声明, 可以改变 数据类型和可变性 let mut a1 = String::new(); }
2.1.2. 数据类型
- 标量类型
pub fn main() { // 整型 let a: u8 = 1; let a: u16 = 1; let a: u32 = 1; let a: u64 = 1; let a: u128 = 1; let b: i8 = -1; let b: i16 = -1; let b: i32 = -1; let b: i64 = -1; let b: i128 = -1; // 依赖计算机架构,64位则为64,32位则为32 let c: isize = -1; let c: usize = 1; // 浮点 let d: f32 = 1.0; let d: f64 = 2.0; // 布尔 let e: bool = true; // 字面量 let mut f = 0b11; f = 0o7; f = 0xff; f = b'c'; // 单字节字符, 仅限 u8 f = 10_000; // 字符, 4个字节, 表示Unicode标量值 let g: char = '😻'; }
- 当整型溢出时, 在debug模式下会报错,在 release 下,会进行 二进制补码回绕
- 复合类型
pub fn main() { // 元组 let a: (i32, u32, bool) = (1, 2, true); // 元组的解构 let (x1, x2, x3) = a; // 元组的访问 let a0 = a.0; // 数组 let b = [1, 2]; let b: [i32; 5] = [1, 2, 3, 4, 5]; let b = [5; 10]; // 重复10个5 // 数组的访问 let b0 = b[0]; }
- 都是分配在栈空间
- 都不可改变大小
2.2. 组织代码块(函数、模块)
2.2.1. 函数
fn plus_all(x: i32, y: i32) -> i32 { x + y }
2.2.2. 模块
- crate
- rust 编译的最小单位
- 有两种形式, 二进制项、库
- 二进制项有个 main 函数
- package (包)
- 使用 cargo 初始化的就是一个包
- src/main.rs 为该包下的一个 二进制 crate
- src/lib.rs 为 库 crate
- 上述两种 crate 的名字与 Cargo.toml 中的 name 同名
- 至少包含一个 crate
- 至多包含一个 库 crate
- 位于 src/bin/*.rs 会被认为是多个 二进制 crate
- 假设有 src/bin/a.rs , src/bin/b.rs 两个文件, 那么运行
cargo build
时,会额外生成 a, b 两个二进制文件
- 假设有 src/bin/a.rs , src/bin/b.rs 两个文件, 那么运行
- 模块
规则如下:
- src/main.rs src/lib.rs 构成 crate 模块 (根模块)
- 声明模块:
- 内联, 在同一文件中, 以
mod mod_a {}
方式声明 - 文件形式,创建
src/mod_a.rs
文件 - 文件夹形式,创建
src/mode_a/mod.rs
文件 - 在 crate 中包含
mod mod_a;
告知编译器导入该文件模块
- 内联, 在同一文件中, 以
- 声明子模块:
- 内联
- 文件形式,创建
src/mod_a/sub_mod.rs
文件 - 文件夹形式,创建
src/mod_a/sub_mode/mod.rs
文件 - 父模块需要包含
mod sub_mod;
来告知编译器导入该子文件模块
- 声明模块或子模块时,如果同时存在上述几种的模式,那么编译器会报错
- 使用
use
可以创建成员的快捷方式, 例如use mod_a::fn_b;
模块及其成员对父模块默认是私有的, 使用
pub
变成公有
- 引用模块
mod sub { pub fn run() {} pub mod b { pub fn run_b() { // 根引用 crate::mod_a::sub::run(); // 自引用 self::bb::run_bb(); bb::run_bb(); } pub mod bb { pub fn run_bb() {} } pub mod bc { pub fn run_bc() { // 父级, 类似与 .. super::bb::run_bb(); } } } }
除了
enum
的成员, 所有成员默认都是私有的
use
的使用
use std::io; // 合并 use use std::{arch, fmt}; // 重命名 use std::fmt::Result as FmtResult; mod mod_b { pub mod mod_c {} } // 导入深层模块, 并导出 pub use self::mod_b::mod_c; // 导入全部 use std::collections::*; // 使用 self use std::collections::{self, HashMap}; fn run() { let a: collections::HashSet<i32> = collections::HashSet::new(); }
惯例:
use
函数时, 层级到父模块, 例如:use mod_a;
, 使用时mod_a::fn();
use
结构体,枚举等其他项时,层级到具体的项,例如use std::collections::HashMap;
2.3. 控制语句
2.3.1. 条件语句
fn main() { let a = 1; let a2 = 1; if a > 0 { println!("a"); } else if a2 < 10 { println!("cc"); } else { println!("b"); } // 赋值 let b = if a > 0 { 1 } else { 2 }; }
2.3.2. 循环语句
fn main() { // 一般形式 let mut a = 1; loop { if a > 4 { break; } a += 1; } // 终止外层循环 let mut b = 1; 'wrap: loop { loop { b += 1; if b > 10 { break 'wrap; } } } // 获取循环的结果 let b = loop { a += 2; if a > 110 { break a * 2; } }; // while let mut a = 1; while a < 10 { a += 1; } // for let a = [1, 2, 3, 4]; for item in a { println!("item is {item}"); } }
2.4. 数据结构
2.4.1. 结构体
- 基本使用
// 声明 struct User { username: String, age: u8, active: bool, } // 元组结构体 struct Color(u8, u8, u8); // 类单元结构体 struct Always; fn main() { // 实例化 let u1 = User { username: String::from("Mike"), age: 10, active: false, }; // 依据其他实例更新现有实例 let mut u2 = User { username: String::from("Mary"), ..u1 }; // 属性 读 let name = u1.username; // 属性 写 u2.age = 12; // 元组结构体实例化 let color = Color(0, 0, 0); println!("{:?}", color.0); // 类单元结构体 let a = Always; }
进阶
mod a { #[derive(Debug)] // 使得 println! 可以打印 pub struct User { pub username: String, age: u8, active: bool, } impl User { // 方法 pub fn is_adult(&self) -> bool { self.age > 18 } // 关联函数 pub fn new(username: String, age: u8) -> User { User { username, age, active: false, } } } // 可以有多个实现 impl User { pub fn age(&self) -> u8 { self.age } pub fn bigger(&self, user: &User) -> bool { self.age > user.age } } } use self::a::User; fn main() { // 调用关联函数 let u1 = User::new(String::from("Mike"), 10); // 调用方法 if u1.is_adult() { println!("{:?} is adult", u1) }; // 只能访问公有字段和方法 println!("name: {:?}, age: {:?}", u1.username, u1.age()); println!("user is {:?}", u1); dbg!(&u1); // 更详细的 debug 输出 }