Rust经验
# 前言
本文是记录在 Rust
开发中遇到的一些小经验,持续更新。
# 关于变量赋值没有使用 mut
在 Rust
中可以使用先声明再赋值的情况,来进行赋值,这是因为 Rust
允许变量绑定被推迟初始化
# 在打印的时候 {}
和 {:?}
的区别
# {}
一种常规的格式化输出语法,用于将数据格式化为字符串并插入到输出中。输出的数据类型实现了 std::fmt::Display
trait
。该值的显示对人阅读比较友好,通常输出变量中的内容
# {:?}
一种调试格式的语法,用于打印调试信息。输出的数据类型实现了 std::fmt::Debug
trait
。输出的内容更加详细,通常输出完整的信息,比如:如果输出的数据是 String
类型,那么显示的值上面会有 "
进行包裹
# 新建文件提示缺少模块声明
在 Rust 2018
后可以不使用 mod.rs
来声明了,所以我目前的做法是在跟目录下增加一个同文件夹名一样的 rs
文件,然后声明,结构如下
├── src
│ ├── main.rs
│ ├── study_enum
│ │ └── test1.rs
│ └── study_enum.rs
2
3
4
5
# 处理错误
在 Rust
中处理错误一般基础采用 match
fn main() {
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("Failed to read line");
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => println!("Please type a number!"),
}
}
2
3
4
5
6
7
8
9
10
# 方便阅读
在 Rust
中为了方便数字的阅读可以采用 _
进行分割,从而达到数字容易阅读的目的
# 注意
在同一行中创建了字符串并立即修改,这在 Rust
中是不允许的
// 错误
fn test2() {
let s = 50_0000;
let s = "100".to_string().push_str(&*s.to_string());
println!("{:?}", s);
}
// 正确
pub fn test2() {
let num = 50_0000;
let mut s1 = "100".to_string();
s1.push_str(&num.to_string());
println!("{}", s1);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# tuple
tuple
(元组),元组本身不支持迭代,所以不要采用迭代的方案处理 tuple
- 小括号元组(
tuple
) - 中括号数组(
array
) - 大括号结构体(
struct
)
# 为什么不能直接返回 x.push_str("xxx")
// 错误
pub fn power_test(mut x: String) -> String {
return x.push_str("ddd")
}
// 正确
pub fn power_test(mut x: String) -> String {
x.push_str("ddd");
x
}
2
3
4
5
6
7
8
9
10
原因是 push_str()
方法返回了类型是 ()
(空元组),而不是 String
;push_str()
是直接修改了原字符串,并没有返回新的字符串;
# 所有权
简单来说呢,就是当变量传递给方法当参数的时候,这个时候变量已经失去了对元素的所有权。
如果要保持其元素还能继续使用的话,那么使用 &
引用传递即可
# 关于 Rust
的编译时检查
其实也没有那么神话,编译时检查仅仅能检查到所有权、借用检查、生命周期、模式匹配、类型检查、范型和特征、错误处理而已,其它的可能性就没有那么屌了
# 关于字符串切片作为参数传递
通常情况下会基于传递的类型是 String
或者 &str
来确定参数类型,但是在 Rust
中可以考虑采用 &str
这个数据类型,这样就可以同时接受 String
和 &str
类型了
使用 &str
时可以是 API
更加通用,而且不会损失任何功能
# Struct
小技巧
字段初始化简写
fn build_user(email: String, username: String) -> User { return User { email, username, active: true, sign_in_count: 1, }; }
1
2
3
4
5
6
7
8结构体更新语法
let user1 = User { // 假设初始化了 ... } let user2 = User { email: String::from("[email protected]"), username: String::from("someusername123"), ..user1, }
1
2
3
4
5
6
7
8
9
# 在 main
函数前面加上 async
关键字是什么意思
- 异步运行时: 使用
async main
需要一个异步运行时(如tokio
或async-std
)来执行这个异步函数。 - 允许使用
.await
: 在异步main
函数中,可以直接使用.await
来等待其它的异步操作完成 - 非阻塞操作:异步的
main
允许程序执行非阻塞的I/O
操作,在处理网络请求、文件操作等场景中特别有用 - 提高并发性:异步编程模型可以更有效地利用系统资源,处理大量并发操作。
# 如何在 RustRover
中启动 Rust
项目时增加行命令参数
# 配置 运行/调试配置
- 点击
Run
->Edit Configurations...
- 选择
Rust
项目 - 点击
+
按钮,选择Command Line Arguments
- 在命令中追加
-- --参数=值
。eg:-- --port=8080
# 如何声明静态的全局变量
pub static APP_VERSION: &'static str = "0.1.0";
# 代码解释
static
关键字,表明它的生命周期和整个程序运行时间相同&'static str
类型,表示一个对字符串字面量的静态引用。'static
生命周期意味着这个引用在整个程序运行期间都有效。- 字符串字面量:
"0.1.0"
是一个字符串字面量,它被直接编译进程序的只读数据段。
# 所有权部分解释
- 对于这种静态字符串,
Rust
编译器会将其存储在程序的只读数据段中。 APP_VERSION
是对这个只读数据的引用,而不是数据本身的所有者。- 由于它是
static
的,你可以在程序的任何地方访问它,而不会有所有权转移的问题。 - 每次你使用
APP_VERSION
,你实际上是在使用这个静态引用,而不是移动或复制数据。