异同之处
不同之处主要在于用途不同
都可以用于Error handle的,都是枚举类型,都可以作为function的返回类型,
二者源码如下
rust
pub enum Option<T> {
None,
Some(T),
}
pub enum Result<T, E> {
Ok(T),
Err(E),
}
为什么这么设计
有场景才有设计的必要,但是你可能会问,那为什么别的语言就没有这么设计,Rust这么设计的原因与Rust的语言设计理念有关,Rust想要尽力做到安全,尽力把不同的场景分开处理,当你想要在程序里设计一个Error handle流程的时候,使用Result是最好的,当你想要返回一个值但是这个值不一定存在的时候,使用Option是最好的,其实在其他语言中,这些可以直接用一个None或者Null的概念来解决,但是这并不是一个好的设计,Null的存在会将这些东西都混为一谈,在一个Null产生的时候,你无法知道究竟是因为你的算法出了问题导致的,还是因为你的输入不合法导致的,又或者是你调用的某个库内部发生了错误,因为你得到的只有一个Null,一个Null把许多不同的情况耦合到了一起,无论发生了什么你都可以返回一个Null,得到Null的人如何理解Null要看他和你的默契。
当然你可以在你的function内每个有可能产生Null的地方都加一个if,然后返回一个errorcode,或者在function内添加log部件,但是这些都不是标准,跟别人合作的时候,调用其他人库的时候,怎么办?
Null的设计者托尼·霍尔,在后来的演讲中多次提到,Null的设计是一个价值10亿美元的错误
引入Result和Option后,根据不同的场景返回不同的内容,就能确保语言的安全性,一旦你的返回值跟收到这个值的人想法不同,代码就跑不起来,直接编译都过不了,这很符合Rust的设计理念,把bug杀死在编译前。
Rust中并不是没有None,只不过是把None的level降低了很多,从一个垃圾桶,变成了一个固定的概念,None在Rust中只代表无,没有,这一个概念。
各自使用方法
- 当你实现了一个function,这个function需要返回一个值,这个值可能存在,也可能不存在,比如在一个hashmap中查找一个key,就可以返回function,有,就是Some(value),没有,就是None
- 当你实现了一个function,这个function可能成功运行,也可能报错,但是你又不想让它直接崩溃,这个时候就用Result。
Option和Result返回值如何使用?
Option和Result都是枚举类型,都可以使用match进行内容提取。Result还可以使用unwrap和except来进行提取,如果结果是Ok则返回数据本身,如果结果是Err则直接崩溃,和panic一个效果,except相较于unwrap的区别是可以自己定义panic崩溃报错内容。
rust
// 使用Option处理可能存在或不存在的值
fn find_element_index(arr: &[i32], target: i32) -> Option<usize> {
for (index, &value) in arr.iter().enumerate() {
if value == target {
return Some(index);
}
}
None
}
// 使用Result处理可能的错误情况
fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
if b == 0 {
Err("Cannot divide by zero")
} else {
Ok(a / b)
}
}
fn main() {
let numbers = [1, 2, 3, 4, 5];
// 使用Option
let index = find_element_index(&numbers, 3);
match index {
Some(i) => println!("Element found at index: {}", i),
None => println!("Element not found"),
}
// 使用Result
match divide(10, 2) {
Ok(result) => println!("Result of division: {}", result),
Err(error) => println!("Error: {}", error),
}
divide(10,2).unwrap();
divide(10,2).expect("defined by yourself");
}