Tip #001
Rust 不支持静态 vec(static vec),但是最接近的是静态数组。例如,如果你想存储三个字符串的数组,可以尝试这样: static STRINGS : [&str;3] = ["a", "b", "c"]
Tip #002
什么是可选值(optional)和 unwrap()? 可以将可选值想象成一个信封,它可以包含一个值(Some(item))或者什么都没有(None)。对可选值调用 unwrap() 要么返回包含的值,要么如果可选值是 None 的话就会使程序panic。
Tip #003
关于可选值( optional)的安全解包方式:
- 使用
match语句明确处理不同情况 unwrap_or_default: 要么解包得到值,要么返回默认值unwrap_or_else: 允许你指定一个函数来处理None/Error解包结果
Tip #004
如果你没有时间完成特定的一段代码,但仍然希望程序可以编译,可以考虑使用 todo!() 或 unimplemented!() 宏。你的代码会继续编译通过,但如果程序运行到包含这些宏的代码块中,它将会panic。
todo!更适合临时标记,而unimplemented!则更适合长期未实现的情况。
Tip #005
如果你想测试一个枚举类型的实例是否符合枚举的特定变体,你可以使用 matches! 宏,例如:let match_res = matches!(my_variable, enum_type);
你也可以匹配其他模式,如范围,例如: matches!(foo, 'A'..='Z')
Tip #006
你知道吗, {} 块可以像函数一样返回结果?这使得基于条件的赋值变得非常容易。例如:
1 | let car_ready = { |
Tip #007
const和static之间有什么区别?
- const值在编译期间会被替换("内联")到你的代码中。这对于在代码的各个地方使用的常量值来说是理想的。
- static值在运行时有一个内存地址,并且会在整个应用程序的生命周期中存在。它们可以是可变的。如果你需要一个固定的位置来存放共享资源,例如硬件驱动程序或数据库接口,那么静态变量就很有用。
Tip #008
如果你想将几个相同或不同类型的值一起存储,元组类型就很有用。下面是一个将元组类型声明为结构体元组的示例,访问元组类型字段,以及从函数返回"匿名"元组类型:
1 | struct MyTuple(String, i32); |
Tips #009
让我们来谈谈 string
在 Rust 中有两种基本的字符串类型: String 和 str。
String: (也称为 Owned String),在堆上分配内存并且可变。String 在运行时使用,当你想要创建和修改字符串时。你可以将 String 作为 &str 引用传递给只读函数。
str: (也称为 String Slice) 是对一序列 UTF8 数据的引用。你可以在编译时以常量、静态字面量的形式创建 str,或者在运行时从 String 对象获取它们。str 总是不可变的。
Tips #010
拼接 string 有两种方式可以将两个字符串连接,分别使用:
- push_str
- format! 宏
1 | // 使用 push_str |
Tips #011
格式化打印宏
print!、println!: 在控制台打印文本。
您可以使用格式字符串打印变量的内容,例如,let a: i32 = 1234; println!("The value of a is: {}", a);将打印出"The value of a is 1234"eprintln!: 打印到标准错误流(stderr)dbg!: 打印变量的值和行号,对于轻量级调试很有用。
Tips #012
可选值解包使用 if let() 类似于 Swift , Rust 允许我们使用 if let 来测试一个可选值是否有值,这种方式便于保持程序流程的简洁:
1 | fn main() { |
Tips #013
使用 if let 解包多个可选值。继上一条 tip,如果你需要同时检查多个可选值是否都有值,你可以使用 if let 来测试和解包可选值的元组:
1 | fn main() { |
Tips #014
实例化 vector。
Vec是一种动态数组类型,非常适合存储相同数据类型的序列。下面是一些使用标准库调用和vec!宏实例化Vec的方式。注意类型是如何处理的:
1 | // Type automatically inferred by the next push. |
1 | // 空Vec |
Tip #015
Vector迭代。
你可以使用 vec.iter() 来对 Vector进行迭代,使用 map() 或 for_each() 函数,这与例如 JavaScript 中的方式类似。
1 | let numbers: Vec<i32> = vec![1, 2, 3, 4, 5]; |
Tips #016
嘿,你有一些不错的HashMap,怎么初始化它们?除了创建一个新的HashMap并插入键值对之外,一种值得注意的方式是使用一个元组数组和一个#迭代器:
1 | use std::collections::HashMap; |
Tips #017
更好的方式来unwrap()
如果内容是None的话,unwrap()一个可选值会导致panic。以下是在unwrap时处理None的一些方法:
- unwrap_or_default(): 如果可选值是None,返回默认值。
- unwrap_or(): 提供一个替代值。
-unwrap_or_else(): 执行一个函数,如果可选值是None的话该函数返回某个值。
1 | fn main() { |
Tips #018
Rust 允许我们轻松定义匿名函数(也称为lambda 或 closure 或闭包)。闭包通常与 iterator 一起使用,或者用于定义回调函数。以下是语法示例:
1 | fn main() { |
Tips #019
在闭包中使用 move 可以从周围作用域捕获变量。这意味着闭包将获取这些变量的所有权,而无需传递任何参数:
1 | fn main() { |
Tips #020
实现 From() trait 提供了一种在复杂类型之间进行转换的机制。Rust 还会自动为对应的类型提供一个 Into() 实现。在下面的示例中,我们为 ColorFloat 实现了 From,但是可以使用 Color8Bit 的 Into():
1 | struct Color8Bit { |
整理自 Daily Rust @rustoftheday
