总体原则
- 在定义一个可能失败的函数时,优先考虑返回 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>### 为验证创建自定义类型之前的猜数游戏```rustuse rand::Rng; // trait 接口定义了随机数生成器需要的方法use std::cmp::Ordering;use std::io; // preludefn main() {println!("猜数!");let secret_number = rand::thread_rng().gen_range(1..101); // i32 u32 i64loop {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!"), // armOrdering::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
