1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use core::panic;
use std::{fs::File, io::{ErrorKind, Error as IOError, Read}};
fn main(){
// err1();
// err2();
guess_number();
}
pub struct Guess{
val:i32,
}
impl Guess {
pub fn new(n:i32) -> Guess{
if n < 1 || n > 100 {
panic!("must be between 1 and 100, got {}",n)
}
Guess{ val:n }
}
pub fn value(&self) -> i32{
self.val
}
}
fn guess_number(){
let guess = "32";
let guess = match guess.trim().parse() {
Ok(n)=>n,
Err(_) => return
};
let guess = Guess::new(guess);
println!("{}",guess.val)
}
fn err2(){
// 错误传播,返回 result
fn read_username_from_file()->Result<String,IOError>{
let f = File::open("io.txt");
let mut f = match f{
Ok(file)=>file,
Err(e) => return Err(e)
};
let mut s = String::new();
return match f.read_to_string(&mut s){
Ok(_) =>Ok(s),
Err(e)=>Err(e)
};
}
let res = read_username_from_file();
// 快捷方式
fn read_username_from_file1()->Result<String,IOError>{
let mut f = File::open("io.txt")?; // 如果是 OK 继续执行,如果是 Err 返回
let mut s = String::new();
f.read_to_string(&mut s)?;// 同上
Ok(s)
}
fn read_username_from_file2()->Result<String,IOError>{
let mut s = String::new();
File::open("io.txt")?.read_to_string(&mut s)?;
Ok(s)
}
let res = read_username_from_file1();
// ? 会被 std::convert::From 隐式处理
// ? 接收的错误类型会被转化为当前函数定义的错误类型
// errA -> errB A 要实现 对应的方法
}
fn err1(){
// 错误类型:可恢复错误(比如文件未找到,可以再次尝试)、不可恢复(比如索引超出范围)
// 可恢复:Result;不可恢复:panic!
// panic 发生时:
// 可以展开调用栈,往回走,每遇到数据就清理掉
// 也可以立即终止调用栈,直接停止程序,OS 清理内存,这样二进制文件就更小了
// 修改 cargo.toml,增加
// [profile.release]
// panic = 'abort'
// 可以设置环境变量 RUST_BACKTRACE=full
// panic!("crash and bin");
// let v = vec![1,2,3];
// println!("{}", v[20]);
// result 枚举,不存在文件先创建
let f = File::open("aa.txt");
let f = match f {
Ok(file)=>file,
// Err(err)=> {
// panic!("{:?}",err);
// }
Err(err)=> match err.kind(){
ErrorKind::NotFound => match File::create("aa.txt"){
Ok(fc)=>fc,
Err(e) =>panic!("error creating file:{:?}",e)
},
other_error => panic!("error opening the file {:?}",other_error)
}
};
// 改良版:unwrap_or_else
let f = File::open("aa.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("aa.txt").unwrap_or_else(|e|{
panic!("error creating file:{:?}",e);
})
} else {
panic!("error opening the file {:?}",error)
}
});
// unwrap:match 表达式的快捷方法,返回 Result 中 OK 里面的值或者调用 panic!
let f = File::open("aa.txt").unwrap();
// expect:和 unwrap 类似,可以指定 panic! 信息,用于自定义错误类型
File::open("abc.txt").expect("不存在");
}