Rust中的关键字Some、Option

Rust中的关键字Some、Option

根据Rust本身的设计哲学, 建议在设计某个变量时, 如果预计该变量某时刻可能会是空值(null/None)的话, 那么尽量用Option/Result来包裹它, 反过来说, 只有你可以肯定该变量不可能为空值时, 才无须这么搞.

rust为了处理情况设置的两个枚举类型,分别是enum Optionenum Result

  • Option的枚举情况有两种,分别是代表有的Some()和代表无的None。 如果是有返回值,则可以通过if let,match,unwrap,?等多种方法对应情况取出Some包裹的值,如果没有则是None。

  • Result的枚举情况也是有两种,表示正确的Ok()和表示错误的Err()。同样也是matchunwrap等等对应方法去提取。分别提取对应情况的内容。

关于枚举

Rust 语言提供了 enum 关键字用于定义枚举。

定义枚举的语法格式如下

enum enum_name {
    
    
   variant1,
   variant2,
   variant3
}

Option

严格的来说,只有 Option 和 Result,Some 只是 Option 的一个值包装类型。
Option类型代表了一个可选的值,每个Option要么是一个Some中包含一个值,要么是一个None。Option的定义如下:

pub enum Option<T> {
    
    
    None,
    Some(T),
}

Option主要有以下一些用法:

  • 初始化值;
  • 作为在整个输入范围内没有定义的函数的返回值;
  • 作为返回值,用None表示出现的简单错误;
  • 作为结构体的可选字段;
  • 作为结构体中可借出或者是可载入的字段;
  • 作为函数的可选参数;
  • 代表空指针;
  • 用作复杂情况的返回值。

我们先来描述一个普通的场景,在很多语言中,获取一个数据可能会返回 null 也可能会没有数据,拿 java 举个例:

User user = model.getUser();

if (user == null) {
    
    
    throw new Exception("用户不存在");
}

System.out.println("你好:" + user.getName());

我们在拿到一个不确定,可能为空的值时,为了确保不出现 NullPointerException 的问题,需要先判断值是否是 null。

这个看起来没什么问题,不过仔细思考,实际上会有两个问题:

  1. 开发者极容易忘记做 null 的判断,实际开发和测试中也许不容易碰到为 null 的情况,导致线上运行报错。
  2. 即使只是为 null 时简单的抛异常,代码也显的有点啰嗦,这种简单的判断能不能少点代码?

Rust 的 Option 就解决了这个问题。
Option 本质上是一个枚举,有两种分别是SomeNone。Some 代表有值,None 则类似于 null,代表无值。

为什么这么搞呢?
Option和T不是同一个类, 不要小看着一个简单的区别,这意味着Option和T是不能直接进行运算的,即Option和i32是不能直接相加的。实际上,更进一步的,在对Option进行T的运算时,必须先将Option转化成T类型。如此一来就可以帮助我们避免以为值非空而实际为空的情况。

例如:

fn main() {
    
    
    let a: i32 = 1;
    let b: Option<i32> = Some(5);
    let c = a + b;
    println!("{}", c);
}

编译器会报如下错误,我们必须先将b从Option类型转化为i32才能进行i32类型的运算。如下

fn main() {
    
    
    let a: i32 = 1;
    let b: Option<i32> = Some(5);
    let c = a + b.unwrap();
    println!("{}", c);
}

每当我们引入一个可能为空的值时,我们必须先把它放到Option里。当我们使用这个值时,我们必须先处理值为空的情况。也就是说,只要一个值不是Option类型的,我们就可以认定它的值不为空。

Rust在写代码和编译时就发现所有的错误,而不是运行时才发现。理解了这一点,你就能理解 Rust 的各种设定。

Some使用举例

let some_value = Some(10);
match some_value {
    
    
	Some(3) => println!("three"),
	_ => println! (“other”),
}

但是,当我们只关心等于3时的情况,用match就感觉代码太多了,那么我们就可以使用if let:

if let Some(3) = some_u8_value {
    
    
	println!("three");
} else {
    
    
	println! (“other”)}

参考

Rust 学习之 Some、Option、Result
参考URL: https://blog.csdn.net/Lee_blog/article/details/120411567

猜你喜欢

转载自blog.csdn.net/inthat/article/details/118995264
今日推荐