Rust语言中Option和Result两种类型的使用

异同之处

不同之处主要在于用途不同

都可以用于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");
}
相关推荐
_.Switch20 分钟前
Python 自动化运维持续优化与性能调优
运维·开发语言·python·缓存·自动化·运维开发
徐*红20 分钟前
java 线程池
java·开发语言
尚学教辅学习资料20 分钟前
基于SSM的养老院管理系统+LW示例参考
java·开发语言·java毕设·养老院
2401_8576363920 分钟前
计算机课程管理平台:Spring Boot与工程认证的结合
java·spring boot·后端
1 9 J22 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship23 分钟前
Java面试题(2)
java·开发语言
J不A秃V头A26 分钟前
Python爬虫:获取国家货币编码、货币名称
开发语言·爬虫·python
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
无尽的大道3 小时前
Java 泛型详解:参数化类型的强大之处
java·开发语言