总体原则
- 在定义一个可能失败的函数时,优先考虑返回 Result
-
编写示例、原型代码、测试
可以使用panic!
你可以确定 Result 就是 Ok: unwrap ```rust use std::net::IpAddr;
fn main() { let home: IpAddr = “127.0.0.1”.parse().unwrap(); }
<a name="vXsSf"></a>
### 错误处理的指导性建议
- 当代码最终可能处于损坏状态时,最好使用 panic!
- 损坏状态(Bad state): 某些假设、保证、约定或不可变性被打破
- 例如非法的值、矛盾的值或空缺的值被传入代码
- 以及下列中的一条
- 这种损坏状态并不是预期能够偶尔发生的事情
- 在此之后,您的代码如果处于这种损坏状态就无法运行
- 在你使用的类型中没有一个好的办法将这些信息(处于损坏状态)进行编码
<a name="Oq7fk"></a>
### 场景建议
- 调用你的代码,传入无意义的参数值:panic!
- 调用外部不可控代码,返回非法状态,你无法修复:panic!
- 如果失败是可预期的:Result
- 当你的代码对值进行操作,首先应该验证这些值:panic!
<a name="aSSaP"></a>
### 为验证创建自定义类型
之前的猜数游戏
```rust
use rand::Rng; // trait 接口定义了随机数生成器需要的方法
use std::cmp::Ordering;
use std::io; // prelude
fn main() {
println!("猜数!");
let secret_number = rand::thread_rng().gen_range(1..101); // i32 u32 i64
loop {
println!("猜测一个数");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("无法读取行");
// shadow
// let guess: u32 = guess.trim().parse().expect("请输入一个数字");
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
if guess < 1 || guess > 100 {
println!("The guess number will be between 1 and 100.");
continue;
}
println!("你猜测的数是: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"), // arm
Ordering::Greater => println!("To big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
- 创建新的类型,把验证逻辑放在构造实例的函数里
- getter: 返回字段数据
- 字段是私有的:外部无法直接对字段赋值 ```rust use rand::Rng; use std::cmp::Ordering; use std::io;
pub struct Guess { value: i32, }
impl Guess { pub fn new(value: i32) -> Guess { if value < 1 || value > 100 { panic!(“Guess value must be between 1 and 100, got {}”, value); } Guess { value } } pub fn value(&self) -> i32 { self.value } }
fn main() { println!(“猜数!”); let secretnumber = rand::thread_rng().gen_range(1..101); loop { println!(“猜测一个数”); let mut guess = String::new(); io::stdin().read_line(&mut guess).expect(“无法读取行”); let guess: i32 = match guess.trim().parse() { Ok(num) => num, Err() => continue, }; // 如果能成功创建实例,说明它通过了验证,如果发生 panic 说明它没有通过验证 let guess = Guess::new(guess); println!(“你猜测的数是: {}”, guess.value); match guess.value.cmp(&secret_number) { Ordering::Less => println!(“Too small!”), // arm Ordering::Greater => println!(“To big!”), Ordering::Equal => { println!(“You win!”); break; } } } } ``` https://docs.rs/rand/0.8.3/rand/trait.Rng.html#method.gen_range