---
title: 可选项
---

[类型系统概述](/zh-cn/book/types#optionals)中提到，所有[原始类型](/zh-cn/book/types#primitive-types)、[结构体](/zh-cn/book/structs-and-messages#structs)和[消息](/zh-cn/book/structs-and-messages#messages)都可以为空。 也就是说，它们不一定有任何值，除了 `null{:tact}` —— 一个特殊的值，表示故意缺少任何其他值。

[变量](/zh-cn/book/statements#let)或[结构](/zh-cn/book/structs-and-messages#structs)和[消息](/zh-cn/book/structs-and-messages#messages)中可容纳 `null{:tact}` 的字段被称为"可选项"。 当变量不一定被使用时，它们对减少状态大小很有用。

在变量或字段的类型声明后添加问号 (`?{:tact}`)，就可以将其设为可选变量或字段。 唯一的例外是 [`map<K, V>{:tact}`](/zh-cn/book/maps)和 [`bounced<Msg>{:tact}`](/zh-cn/book/bounced)，你不能让它们、内部键/值类型（如果是 map）或内部[消息](/zh-cn/book/structs-and-messages#messages)（如果是 bounced）成为可选项。

未定义的可选变量或可选字段默认持有`null{:tact}`值。 您必须先检查`null{:tact}`，否则无法访问它们。 但如果你确定它们在某一时刻不是 `null{:tact}`，可以使用[非空断言操作符 `!!{:tact}`](/zh-cn/book/operators#unary-non-null-assert)访问它们的值。

在未使用 [`!!{:tact}`](/zh-cn/book/operators#unary-non-null-assert)或未事先检查 `null{:tact}` 的情况下尝试访问可选变量或可选字段的值，如果编译器可以跟踪，则会导致编译错误；如果不能跟踪，则会导致[退出码 128](/zh-cn/book/exit-codes#128)异常：空引用异常。

可选项举例：

```tact
struct StOpt {
    opt: Int?; // Int or null
}

message MsOpt {
    opt: StOpt?; // Notice, how the struct StOpt is used in this definition
}

contract Optionals {
    opt: Int?;
    address: Address?;

    init(opt: Int?) { // optionals as parameters
        self.opt = opt;
        self.address = null; // explicit null value
    }

    receive(msg: MsOpt) {
        let opt: Int? = 12; // defining a new variable
        if (self.opt != null) { // explicit check
            self.opt = opt!!; // using !! as we know that opt value isn't null
        }
    }
}
```
