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");
}
相关推荐
碳苯1 分钟前
【rCore OS 开源操作系统】Rust 枚举与模式匹配
开发语言·人工智能·后端·rust·操作系统·os
结衣结衣.14 分钟前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
学习使我变快乐16 分钟前
C++:静态成员
开发语言·c++
TJKFYY16 分钟前
Java.数据结构.HashSet
java·开发语言·数据结构
kylinxjd18 分钟前
spring boot发送邮件
java·spring boot·后端·发送email邮件
杰哥在此25 分钟前
Python知识点:如何使用Multiprocessing进行并行任务管理
linux·开发语言·python·面试·编程
小白学大数据26 分钟前
User-Agent在WebMagic爬虫中的重要性
开发语言·爬虫·http
ROBIN__dyc32 分钟前
C语言基本概念
c语言·开发语言
zaim13 小时前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
学习使我变快乐3 小时前
C++:const成员
开发语言·c++