# 5.2 合约存储(Contract Storage)

When developing a [smart contract](https://fuellabs.github.io/sway/v0.38.0/book/sway-program-types/smart_contracts.html), you will typically need some sort of persistent storage. In this case, persistent storage, often just called _storage_ in this context, is a place where you can store values that are persisted inside the contract itself. This is in contrast to a regular value in _memory_, which disappears after the contract exits.

在开发[智能合约](https://fuellabs.github.io/sway/v0.38.0/book/sway-program-types/smart_contracts.html)时，你通常需要某种持久性存储。在这种情况下，持久性存储，在这里通常被称为 _storage_，是一个你可以在合约本身中持久存储值的地方。这与 _memory_ 中的普通值不同，后者在合约退出后就会消失。

Put in conventional programming terms, contract storage is like saving data to a hard drive. That data is saved even after the program which saved it exits. That data is persistent. Using memory is like declaring a variable in a program: it exists for the duration of the program and is non-persistent.

用传统的编程术语来说，合约存储就像把数据保存在硬盘上。即使在保存数据的程序退出后，这些数据也会被保存。该数据是持久的。使用(传统)存储就像在程序中声明一个变量：它存在于程序的持续时间内，是不持久的。

Some basic use cases of storage include declaring an owner address for a contract and saving balances in a wallet.

存储的一些基本用例，包括为一个合约声明一个所有者地址，以及在钱包中保存余额。

### 通过`storage`关键字进行存储访问 (Storage Accesses Via the `storage` Keyword)

Declaring variables in storage requires a `storage` declaration that contains a list of all your variables, their types, and their initial values as follows:

在存储中声明变量需要一个`storage`声明，其中包含所有变量的列表，它们的类型，以及它们的初始值，如下所示：

```
struct Type1 {
    x: u64,
    y: u64,
}

struct Type2 {
    w: b256,
    z: bool,
}

storage {
    var1: Type1 = Type1 { x: 0, y: 0 },
    var2: Type2 = Type2 {
        w: 0x0000000000000000000000000000000000000000000000000000000000000000,
        z: false,
    },
}


```

To write into a storage variable, you need to use the `storage` keyword as follows:

要写进一个存储变量，你需要使用`storage`关键字，如下所示：

```
    #[storage(write)]
    fn store_something() {
        storage.var1.x.write(42);
        storage.var1.y.write(77);
        storage.var2.w.write(0x1111111111111111111111111111111111111111111111111111111111111111);
        storage.var2.z.write(true);
    }

```

To read a storage variable, you also need to use the `storage` keyword as follows:

要读取一个存储变量，你还需要使用`storage`关键字，如下所示：

```
    #[storage(read)]
    fn get_something() -> (u64, u64, b256, bool) {
        (
            storage.var1.x.read(),
            storage.var1.y.read(),
            storage.var2.w.read(),
            storage.var2.z.read(),
        )
    }

```

### 存储映射 (Storage Maps)

Generic storage maps are available in the standard library as `StorageMap<K, V>` which have to be defined inside a `storage` block and allow you to call `insert()` and `get()` to insert values at specific keys and get those values respectively. Refer to [Storage Maps](https://fuellabs.github.io/sway/v0.38.0/book/common-collections/storage_map.html) for more information about `StorageMap<K, V>`.

通用的存储映射在标准库中以 `StorageMap<K, V>`的形式存在，必须在 `storage` 区块中定义，并允许你调用 `insert()`和 `get()`来分别在特定的键上插入值和获取这些值。关于 `StorageMap<K, V>`的更多信息，请参考[Storage Maps](https://fuellabs.github.io/sway/v0.38.0/book/common-collections/storage_map.html)。

### 手动存储管理 (Manual Storage Management)

It is possible to leverage FuelVM storage operations directly using the `std::storage::storage_api::write` and `std::storage::storage_api::read` functions provided in the standard library. With this approach you will have to manually assign the internal key used for storage. An example is as follows:

可以直接使用标准库中提供的`std::storage::storage_api::write`和`std::storage_api::read`函数来利用FuelVM的存储操作。使用这种方法，你将不得不手动分配用于存储的内部密钥。一个例子是这样的：

```
contract;

use std::storage::storage_api::{read, write};

abi StorageExample {
    #[storage(write)]
    fn store_something(amount: u64);

    #[storage(read)]
    fn get_something() -> u64;
}

const STORAGE_KEY: b256 = 0x0000000000000000000000000000000000000000000000000000000000000000;

impl StorageExample for Contract {
    #[storage(write)]
    fn store_something(amount: u64) {
        write(STORAGE_KEY, 0, amount);
    }

    #[storage(read)]
    fn get_something() -> u64 {
        let value: Option<u64> = read::<u64>(STORAGE_KEY, 0);
        value.unwrap_or(0)
    }
}

```

> **Note**: Though these functions can be used for any data type, they should mostly be used for arrays because arrays are not yet supported in `storage` blocks. Note, however, that _all_ data types can be used as types for keys and/or values in `StorageMap<K, V>` without any restrictions.
>
> **注意**： 虽然这些函数可以用于任何数据类型，但它们应该主要用于数组，因为数组在`storage` 区块中还不被支持。但是请注意，\_所有的数据类型都可以在`StorageMap<K, V>`中作为键和/或值的类型，没有任何限制。
