Rust 学习笔记(11)-Option

我们之前提到了在Rust中有一个非常常用的枚举 Option,它的原型是如下的样子

1
2
3
4
enum Option<T> {
    None,
    Some(T),
}

它代表了有值和没有值的情况,成员 None 代表没有值,也就是空值的情况,Some(T) 代表了有值的情况,换句话说 Option<T> 代表了一个可能为空的值

Option<T> 枚举是如此有用以至于它甚至被包含在了 prelude 之中,你不需要将其显式引入作用域。另外,它的成员也是如此,可以不需要 Option:: 前缀来直接使用 Some 和 None。即便如此 Some(T) 和 None 仍是 Option 的成员。

这有什么好处或者说什么用处呢?Rust为什么要这么设计它?它和其他语言中的null有什么不同?下面我说说我的见解

在其他语言中,空值通常由 nullnil 来表示,当一个变量的值是 null 时,如果你尝试使用它,程序很可能会崩溃,因为编译器并不知道这个变量的值是什么,换句话说,编译器并不知道这个变量的值是否是一个有效值,因为null也是一个,只不过它是一个有特殊意义的值 ,它可能在运行时因某种情况被赋予变量,而当你尝试像一个非空值那样使用一个空值,程序很可能就会崩溃。

而Rust通过 Option<T> 将空值的检查放到了编译期,编译器会确保我们在使用值之前处理了为空的情况。

例如这段代码就无法通过编译

1
2
3
4
    let x: i8 = 5;
    let y: Option<i8> = Some(5);

    let sum = x + y;

上面的例子会报错, cannot add Option<i8> to i8 Rust 不知道该如何将 Option<i8>i8 相加,因为它们的类型不同。

而要转换为 T,你就必须处理空值的情况,告诉Rust,如果这个值无效,则返回什么东西

你可能会问,为什么不允许直接用 Option<T> 和其他类型做运算?非要转换一下?

  • 第一点是因为类型不同
1
我们知道在强类型语言中,两个类型不同的值是不能做运算的,因此编译器需要先将 Option<T> 类型转换成 T 类型
  • 第二点是因为Rust不允许像一个肯定有效的值那样使用 Option<T>
1
2
想象一下,如果允许直接用 Option<T> 类型和其他类型做运算,我们知道 Option<T> 是包含两种情况的,一种是代表 null 的空值,一种是有实际值的情况  
假如这个值无效,那么就会变成 x + null 这样肯定程序就会崩溃。 所以,在Rust中不允许我们这么做

简单来说,Rust强制你在使用 Option<T> 之前处理为空的情况

总结一下

  1. Option<T> 是一个代表包含有有效值无效值的类型
  2. 在使用 Option<T> 之前必须将其转换为实际的 T 类型
  3. Option<T> 将其他语言中常见的 null类型转换异常 的问题,由运行时转移到了编译期
updatedupdated2025-03-012025-03-01