Solidity 中的 mapping 是什么?
作者 Alchemy
Solidity 中的映射(mapping)是以键值对形式存储数据的哈希表,其中键可以是 Ethereum 支持的任意内置数据类型。映射是学习 Solidity 开发时需要理解的基础概念。
本文将介绍映射是什么、映射如何工作、映射与数组的区别,并给出映射的示例,帮助你在 Ethereum 及 Optimism、Arbitrum 等兼容 Solidity 的区块链上开发出更好的智能合约。
什么是哈希表?
哈希表是一种以关联方式存储数据的数据结构。哈希表中的数据以数组形式保存,每个数据值都有自己唯一的索引值。哈希表使用数组作为存储介质,并利用哈希技术建立索引,用于插入或定位元素。

当所需数据的索引已知时,可以极快地返回该数据。因此,无论数据量多大,哈希表的插入和查找操作都非常快速。
Solidity 中的映射是什么?
映射是 Solidity 中的一种哈希表,以键值对形式存储数据,其中键可以是除引用类型之外的任意内置数据类型,值的数据类型则可以是任意类型。
在 Solidity 和 Ethereum 区块链中,映射最常见的用途是将唯一的 Ethereum 地址关联到对应的值类型。
在其他编程语言中,映射相当于字典(dictionary)。
哈希表与 Solidity 映射有什么区别?
映射的作用类似于哈希表,由键类型与对应的值类型组成键值对,其价值在于可以容纳大量的 KeyType 到 ValueType 的映射关系。映射没有长度,也没有设置键或值这一概念。映射只适用于作为存储引用类型的状态变量。映射初始化时,会包含所有可能的键,并将其映射到字节表示全为零的值。
Solidity 中定义映射的方式与定义其他变量类型相同:
Solidity 数组与映射有什么区别?
Solidity 数组更适合遍历一组数据(例如使用 for 循环),而映射则更适合在已知键的情况下获取值(即无需遍历数据)。
由于在 Solidity 中遍历数组的成本可能比从映射中获取数据更高,而开发者有时既需要在智能合约中存储值,也需要存储对应的键,因此开发者有时会创建一个键的数组,作为引用,之后再从映射中检索对应数据。
开发者不应让 Solidity 中的数组增长过大,因为遍历一个大数组所耗费的 Solidity gas 费用可能超过交易本身的价值,这使得映射成为更节省 gas 的智能合约实现方式。
关于映射,还有以下一些特性:
- 映射没有长度。
- 映射也不存在“设置”键或值这一概念。
- 映射只能用于作为存储引用类型的状态变量。
什么是嵌套映射?
嵌套映射是指从一个映射映射到另一个映射。例如,如果我们有用户名和年龄信息,并希望借助一个特殊的 ID 来存储这些信息,使得其他人只能通过该 ID 获取这些信息,这在 Solidity 中被称为双重映射。
下面是一个嵌套映射的示例:
在这个合约中,我们构建了一个嵌套映射,称为 User。在该映射中,我们关联了两个映射:
- 一个用于记录特定用户 id 的相关信息;
- 一个用于存储特定用户的姓名和年龄。
下面的代码块是一个简单的 getter 函数,用于返回用户的信息。
如何在 Solidity 中使用映射
以下是在 Solidity 中使用映射的示例。以下代码片段的功能是:
- 从 address 映射到 uint,并确保映射始终返回一个值
- 如果该值从未被设置过,则返回默认值。
- 更新映射地址对应的值
- 将值重置为默认值。
- 创建从 address 到另一个映射的嵌套映射
- 即使嵌套映射未初始化,也能从中获取值
Solidity 映射示例
以下是 Solidity 中映射的三个示例:
- ERC20 代币余额
- 使用布尔逻辑
- 查询 DAO 成员
1. ERC20 用户余额
此代码片段将用户地址映射到其地址对应的 ERC20 余额。
2. Solidity 布尔类型映射示例
此代码片段旨在列出候选人名单,并返回每位候选人获得的票数。此示例在 DAO 中有实际应用场景,成员需要对组织事务进行投票。
3. 是否为成员(DAO)
此示例来自 Dominion DAO 智能合约,其中映射了 raisedProposals、stakeholderVotes、votedOn、contributors 和 stakeholders。
此代码示例列出了两个 Solidity 结构体的字段:ProposalStruct 和 VotedStruct。
Solidity 字符串映射
为了更好地理解,我们在构建映射的过程中尝试添加一些值。在以下示例中,我们将:
- 创建一个合约
- 定义一个结构体
- 声明不同的结构体元素
- 创建一个映射
- 向映射中添加值
Solidity 映射常见问题
以下是关于 Solidity 映射的一些常见问题:
- Solidity 映射的长度是多少?
- Solidity 映射的默认值是什么?
- 如何公开查看 Solidity 映射?
Solidity 映射的长度是多少?
映射没有长度。键的数据本身并不保存在映射中,而是使用其 keccak256 哈希值来存储该键所指向的值。因此不存在单独意义上的“键”和“值”这一概念。
Solidity 映射默认值类型是什么?
以下是 Solidity 映射的默认值类型:
- int/uint - 键类型 = 是;值类型 = 是
- string - 键类型 = 是;值类型 = 是
- byte/bytes - 键类型 = 是;值类型 = 是
- address - 键类型 = 是;值类型 = 是
- struct - 键类型 = 否;值类型 = 是
- mapping - 键类型 = 否;值类型 = 是
- enum - 键类型 = 否;值类型 = 是
- contract - 键类型 = 否;值类型 = 是
- fixed-sized array - 键类型 = 是;值类型 = 是
- dynamic-sized array - 键类型 = 否;值类型 = 是
- multi-dimensional array - 键类型 = 否;值类型 = 是
- variable - 键类型 = 否;值类型 = 否
如何公开查看 Solidity 映射?
由于该属性是 public 的,你可以使用 Solidity 编译器生成的 getter 函数来访问它。
相关概览

构建区块链应用
Alchemy 将最强大的 Web3 开发者产品和工具与资源、社区及专业支持结合在一起。


