# 解构Option

在枚举那章，提到过`Option`枚举, 它用来解决Rust中变量是否有值的问题，定义如下:
```rust
enum Option<T> {
    Some(T),
    None,
}
```
简单解释就是： **一个变量要么有值:`Some(T)`, 要么为空: `None`**.

那么现在的问题就是该如何去使用这个`Option`枚举类型，根据我们上一节的经验，可以通过`match`来实现。

> 因为`Option`,`Some`，`None`都包含在`prelude`中，因此你可以直接通过名称来使用它们，而无需以`Option::Some`这种形式去使用，总之，千万不要因为形式变短了，而忘记`Some`和`None`也是`Option`底下的枚举成员！

## 匹配 `Option<T>`

使用`Option<T>`，是为了从 `Some` 中取出其内部的 `T` 值以及处理没有值的情况，为了演示这一点，下面一起来编写一个函数，它获取一个 `Option<i32>`，如果其中含有一个值，将其加一；如果其中没有值，则函数返回 `None` 值：

```rust
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
```

`plus_one`接受一个`Option<i32>`类型的参数，同时返回一个`Option<i32>`类型的值(这种形式的函数在标准库内随处所见)，在该函数的内部处理中，如果传入的是一个`None`，则返回一个`None`切不做任何处理；如果传入的是一个`Some(i32)`，则通过模式绑定，把其中的值绑定到变量`i`上，然后返回`i+1`的值，同时用`Some`进行包裹。


为了进一步说明，假设`plus_one`函数接受的参数值x是`Some(5)`， 来看看具体的分支匹配情况:

#### 传入参数`Some(5)`
```rust,ignore
None => None,
```
首先是匹配`None`分支，因为值`Some(5)` 并不匹配模式 `None`，所以继续匹配下一个分支。

```rust,ignore
Some(i) => Some(i + 1),
```

`Some(5)` 与 `Some(i)` 匹配吗？当然匹配！它们是相同的成员。`i` 绑定了 `Some` 中包含的值，因此 `i` 的值是 `5`。接着匹配分支的代码被执行，最后将 `i` 的值加一并返回一个含有值 `6` 的新 `Some`。

#### 传入参数None
接着考虑下`plus_one` 的第二个调用，这次传入的`x` 是`None`， 我们进入 `match` 并与第一个分支相比较。

```rust,ignore
None => None,
```

匹配上了！接着程序继续执行该分支后的代码：返回表达式`None`的值，也就是返回一个`None`，因为第一个分支就匹配到了，其他的分支将不再比较。

