Gas 消耗:mapping 的写入和读取操作通常是高效的,但 Gas 消耗并非完全固定,写入操作的 Gas 消耗与 mapping 的大小(即已存储的键值对数量)以及值的复杂程度有关,读取操作在键存在时 Gas 消耗相对固定,但如果键不存在,在某些情况下可能会有轻微差异,总体而言,mapping 是区块链上相对节省 Gas 的数据结构之一。
动态性与无长度限制:mapping 的大小是动态的,它不会预先分配固定大小的空间,你可以在任何时候向其中添加新的键值对,理论上键值对的数量只受限于区块链的存储限制和 Gas 限制,没有直接的 length 属性来获取 mapping 中元素的数量。
迭代限制:Solidity 目前不支持直接遍历 mapping 中的所有键或值,你不能像遍历数组那样使用 for 循环来获取 mapping 中的所有元素,这是因为 mapping 的设计初衷就是高效的键值查找,而不是迭代,如果你需要迭代功能,通常需要结合数组来实现,例如维护一个键的数组。
Mapping 的应用场景
mapping 在智能合约中有着广泛的应用,以下是一些常见的场景:
余额管理:这是最经典的用法之一,一个 ERC20 代币合约可以使用 mapping(address => uint256) public balances; 来跟踪每个地址的代币余额。
mapping(address => uint256) public balances;
function transfer(address to, uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
}
权限控制:可以使用 mapping 来记录哪些地址拥有特定权限。mapping(address => bool) public isOwner; 来记录合约所有者。