Solidity 映射 mapping

Solidity 映射 mapping 用于以键值对的形式存储数据,等同于其它编程语言的哈希表或字典。

映射 mapping 是智能合约中很常用的一种数据类型,它是引用类型。

下面是声明映射类型的语法。

mapping(_KeyType => _ValueType)
  • _KeyType:可以是任何内置类型,或者 bytes 和 字符串。不允许使用引用类型或复杂对象。
  • _ValueType: 可以是任何类型。

注意

  • 映射的数据位置(data location)只能是 storage,通常用于状态变量。
  • 映射可以标记为 public,Solidity 自动为它创建 getter。

映射可以视作哈希表 ,它们在实际的初始化过程中创建每个可能的 key,并将其映射到字节形式全是零的值:一个类型的 默认值。

映射与哈希表不同:在映射中,实际上并不存储 key,而是存储它的 keccak256 哈希值,从而便于查询实际的值。

正因为如此,映射是没有长度的,也没有 key 的集合或 value 的集合的概念。映射只能是存储的数据位置,因此只允许作为状态变量或作为函数内的存储引用 或 作为库函数的参数。 它们不能用于合约公有函数的参数或返回值。

可以将映射声明为 public,然后来让 Solidity 创建一个 getter 函数。 _KeyType 将成为 getter 的必须参数,并且 getter 会返回 _ValueType。

 

1. 状态变量示例

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract LedgerBalance {
   mapping(address => uint) public balances;

   function updateBalance(uint newBalance) public {
      // 设置 mapping 的 key 和 value
      balances[msg.sender] = newBalance;
   }

   function get() public view returns(uint){
       // 通过 key 获取 mapping 的 value
       return balances[msg.sender];
   }
}

contract Updater {
   function updateBalance() public returns (uint) {
      LedgerBalance ledgerBalance = new LedgerBalance();
      ledgerBalance.updateBalance(10);
      return ledgerBalance.get();
   }
}

运行上述程序,先单击 updateBalance 按钮将值设置为 10,然后查看日志输出:

{
   "0": "uint256: 10"
}

2. 局部变量示例

mapping 类型可以用做局部变量,但只能引用状态变量,而且存储位置为 storage。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract LedgerBalance {
    mapping(address => uint) public balances;
    
   function updateBalance() public returns (uint) {
      // mapping 局部变量 ref 引用状态变量 balances
      mapping(address => uint) storage ref = balances;
      ref[msg.sender] = 3;
      return 0;
   }
}

下一章:Solidity 枚举 enum

solidity 的枚举类型 enum 是一种用户自定义类型,用于表示多种状态。枚举类型 enum 内部就是一个自定义的整型,默认的类型为uint8,当枚举数足够多时,它会自动变成uint16。枚举类型 e ...