开发rust程序过程中遇到的问题以及解决方法
错误处理
-
对于
Result
、Option
等类型,如果使用unwrap
、expect
等方法,会直接导致panic -
对于
Result
类型,如果遇到错误只需要返回None
,那么可以使用如下简单的语法来替代match
:1
let some_var = something_that_returns_result().ok()?;
其中,
Result::ok()
函数将Result
转换为Option
:- 对于
Ok(val)
,返回Some(val)
; - 对于
Err(some_error)
,返回None
?
提取Option
中的内容,如果为None
,则返回None
- 对于
slice复制
使用copy_from_slice将一个slice的内容复制到另外一个slice时,要求两个slice的长度相同,因此对于要将[u8]转为[u8; usize]的场景,需要使用以下代码:
1 | let v: Vec<u8> = vec![1,2,3]; |
关于所有权
-
定长的变量存放在栈中,默认实现
Copy
特征,拷贝时直接在栈上复制一个副本,为浅拷贝 -
不定长或可变的变量存放在堆中,并将其对应的指针压入栈中,拷贝时会转移所有权,若需要原变量也保持所有权,需要进行深拷贝,即将堆中存放的数据也拷贝一份
循环
使用方法 | 等价使用方式 | 所有权 |
---|---|---|
for item in collection |
for item in IntoIterator::into_iter(collection) |
转移所有权 |
for item in &collection |
for item in collection.iter() |
不可变借用 |
for item in &mut collection |
for item in collection.iter_mut() |
可变借用 |
Trait
-
孤儿规则:如果你想要为类型
A
实现特征T
,那么A
或者T
至少有一个是在当前作用域中定义的- eg:无法在当前作用域中,为
String
类型实现Display
特征,因为它们俩都定义在标准库中,其定义所在的位置都不在当前作用域
- eg:无法在当前作用域中,为
-
调用方法需要引入特征:
1
2
3
4
5
6
7
8
9
10
11
12
13use std::convert::TryInto;
fn main() {
let a: i32 = 10;
let b: u16 = 100;
let b_ = b.try_into()
.unwrap();
if a < b_ {
println!("Ten is less than one hundred.");
}
} -
特征对象:
Box<dyn Trait>
或&dyn Trait
Box::leak
需要一个在运行期初始化的值,但是可以全局有效,也就是和整个程序活得一样久
-
eg. 可以把一个
String
类型,变成一个'static
生命周期的&str
类型:1
2
3
4
5
6
7
8
9
10
11fn main() {
let s = gen_static_str();
println!("{}", s);
}
fn gen_static_str() -> &'static str{
let mut s = String::new();
s.push_str("hello, world");
Box::leak(s.into_boxed_str())
}
Stack overflow
例如定义一个跳表节点
1 | struct Node { |
若跳表中节点很多,则在drop头节点时,默认会采用递归的方式来清除,这样会导致爆栈,因此需要自定义迭代方式的drop
1 | impl Drop for Node { |