Rust里的错误处理主要分两种: Panic 和 Result
💀Panic
- 不像C++的未定义操作, painc时的操作顺序:- 打印错误信息, 如果定义了RUST_BACKSTRACE=1, 还将打印堆栈;
- 栈回溯, 按照堆栈顺序销毁资源, 所有类型(含自定义类型)的drop方法被调用;
- 线程退出, Panic是线程级, 如果主线程崩了, 整个进程结束, 否则其它线程还会继续.
 
- 打印错误信息, 如果定义了
- 可以用std::panic::catch_unwind()捕获panic时的stack unwinding, 这也是Rust test的做法.
- 当C/C++等其它语言调用Rust代码时可以用std::panic::catch_unwind()捕获, 因为unwinding 非Rust code 的行为是未定义的.
- std::panic::catch_unwind()只能用于恢复堆栈, 不要尝试着继续运行.
- 如果清理过程中drop方法再次panic, 则Rust不会再尝试恢复堆栈unwind stack, 直接abort.
⚖️Result<T,E>
| 1 | pub enum Result<T, E> { | 
T, E 分别定义Ok和Err包含的类型:
- Ok(T)
- Err(E)
- Result有两个方法: - .as_ref()和- .as_mut()分别把- Result<T, E>转为- Result<&T, &E>和- Result<&mut T, &mut E>从而避免销毁它或者move.
- fn remove_file(path: &Path) → Result<()>, 这里的Result是别名(aliases), 需要看对应的模块的public Result定义:- 1 - pub type Result<T> = result::Result<T, Error> 
- 通过 - println!("{:?}", err);可以查看到更多的技术性错误信息;- err.description()以- &str方式返回错误信息;
- err.cause()返回- Option<&Error>: 内部错误详细信息.
 
- 用 - ?向上抛出Err, 只能用于返回- Result的函数
- errorchaincrate 可以用于定义error type, 方便- ?抛出不同类型Err
Custom Error Type
- 通常直接定义错误信息结构体, 然后用 - Err()抛出就够了- 1 
 2
 3
 4
 5
 6
 7
 8
 pub struct JsonError {
 pub message: String,
 pub line: usize,
 pub column: usize,
 }
 return Err(JsonError {...});
- 如果希望和标准库的错误类型表现一致, 还需要定义 - fmt::Display和- Error的trait.- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- use std; 
 use std::fmt;
 // Errors should be printable
 imple fmt::Display for JsonError {
 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
 write!(f, "{} ({}:{})", self.message, self.line, self.column);
 }
 }
 // Errors should implement the std::error::Error trait.
 impl std::error::Error for JsonError {
 fn description(&self) -> &str {
 &self.message
 }
 }
