一、前言
本章将要介绍的是Rust中的错误处理方式,这是一个与其它很多语言都非常不同的一点。
但在Rust的代码中,你也将会非常频繁的遇到它,所以为了更进一步学习Rust中的其它特性,这里有必要对Rust
中的错误处理进行学习。
二、不同之处
就目前来说,各类编程语言中主流的就两种错误形式:返回错误码,抛出异常。
其中,c语言就是典型采用的返回错误码方式,比如最常见的NULL
代表空指针等等,这一般就标志一个错误的产生。
至于C++中,错误码与异常都在用,不过大多数时候仍然是错误码用的比较多。
究其原因是异常带来的性能损耗,很多人不愿意承担,所以选择了性能更高、但不友好的返回错误码方式。
而在JAVA
这门语言中,绝大多数采用的都是抛出异常的方式。
java中有句笑话是,只要我将所有代码都try
起来,那就没有错误!
这两种处理错误的方式各有优缺点,异常的主要缺点是其带来的性能损耗,这一点是作为一门对标系统级开发语言的rust
所无法忍受的。
而如果采用返回错误码的方式(比如NULL
),作为以代码安全标榜自身的Rust
语言,同样无法接受。
但如果不采取这两种方式,那还有其它方式能完成这一目标吗?
有,那就是枚举!
三、枚举处理错误
那么枚举是如何处理错误的呢?我们可以直接看一个例子。
为了更加深刻的体会到枚举处理错误所带来的优势,我们首先使用C语言的方式,采用返回错误码来实现错误处理:
//写一个除法函数,传入 除数,返回100除以这个除数的结果
fn divi(i:u32) -> u32 {
if i==0{
//0不能作为除数,所以返回0作为错误发生
0
}else{
//正确,则返回运算的结果
100/i
}
}
这是一个非常简单的函数,传入一个除数,返回100
除以它的结果,如果这个除数为0
,就说明发生了错误,那就直接返回0作为错误码,否则返回正确的结果。
注意这里返回值的方式使用的是上一章提到的“表达式”,不理解的回去看一看。
那么在调用这个函数处理其结果时,一般就得像下面这样用:
fn main() {
let ret=divi(0);
if ret==0{
println!("函数调用出错");
}else{
println!("执行结果为:{}",ret);
}
}
在c语言中,我们平常写代码基本就是这样写的吧!
这样写可以吗?当然可以!只是不够安全!
因为如果你不看这个函数的使用方式,你就不知道它的错误码是多少,有些时候甚至你会直接忽略处理它的错误码、把它的结果当作正常返回值继续使用。
毕竟,它的返回值与错误码都是数字,根据墨菲定律,只要存在这种事情发生的可能性,那么它就已经会发生,这里同理,只要它可能被人滥用出错,那么就一定会出现滥用出错的事情。
不安全的代码行为,在rust中默认都是不被允许的,所以就出现了用枚举的方式来处理错误,现在我们再将上面的代码做一下处理:
enum Result{
Ok(u32),
Err(String)
}
//写一个除法函数,传入 除数,返回100除以这个除数的结果
fn divi(i:u32) -> Result {
if i==0{
//0不能作为除数,返回Err,并携带错误的原因
Result::Err("传入的参数不能为0".to_string())
}else{
//正确,返回Ok,并携带正常的结果
Result::Ok(100/i)
}
}