做网站建网站武汉网站开发公司
在区块链的智能合约开发领域,Solidity 作为以太坊上最主流的编程语言之一,拥有诸多强大特性助力开发者构建复杂且高效的去中心化应用。其中,映射(Mapping)是一个极为关键的数据结构,它为合约中的数据存储与检索提供了便捷、高效的方式。
本篇代码为自己结合资料总结,如有错误还请各位随时指出并进行修改~感恩包容理解!
另所有本篇以及以前出现的代码均可以在本人GitHub GitHub - solidity学习代码 上找到
一、映射的基础概念
在 Solidity 中,映射如同一个神奇的 “账本”,能够以键值对的形式存储数据。以代码中的 mapping(address => uint ) public balances; 为例,它创建了一个从以太坊地址(address 类型)到无符号整数(uint 类型)的映射关系,通俗来讲,就是可以针对不同的以太坊地址记录对应的余额数值。这就像是现实世界银行给每个客户设立账户并记录存款余额,只不过这里的 “账户” 是以太坊地址,“余额” 是合约中所关心的各种数值信息。
映射是一种键值对的数据结构,类似于传统编程语言中的哈希表或字典。在Solidity中,映射用于将一个值(键)映射到另一个值(值)。其基本语法如下:
mapping(_KeyType => _ValueType) _mappingName;
_KeyType
:键的类型,可以是任何基本类型,如address
、uint
、bytes32
等,但不能是复杂类型如结构体或数组._ValueType
:值的类型,可以是任何类型,包括基本类型、复杂类型、甚至是另一个映射._mappingName
:映射的名称,用于在合约中引用该映射.
例如,在上面的代码中,mapping(address => uint) public balances;
定义了一个名为balances
的映射,它将address
类型的键映射到uint
类型的值.这意味着我们可以用一个地址作为键,来存储和检索与该地址相关的余额信息.
映射的操作
设置值
要为映射设置值,可以直接使用赋值操作符=
.例如:
balances[msg.sender] = 123;
这行代码将调用者(msg.sender
)的地址作为键,将值123
存储到balances
映射中.这意味着调用者的余额被设置为123.
获取值
获取映射中的值也非常简单,只需通过键来访问:
uint bal = balances[msg.sender];
这里,我们通过调用者的地址作为键,从balances
映射中获取其余额,并将其存储在变量bal
中.
删除值
如果需要删除映射中的某个键值对,可以使用delete
关键字:
delete balances[msg.sender];
这将删除调用者地址对应的键值对,并将值恢复为其类型的默认值.对于uint
类型,其默认值是0,所以删除后,调用者的余额会变成0.
嵌套映射
Solidity中的映射可以嵌套,即值类型可以是另一个映射.这为存储更复杂的数据关系提供了可能.例如:
mapping(address => mapping(address => bool)) public isFriend;
这里定义了一个名为isFriend
的嵌套映射,它将两个address
类型的键映射到一个bool
类型的值.这可以用来表示两个地址之间的朋友关系.例如:
isFriend[msg.sender][address(this)] = true;
二、写在介绍后
总结下本篇出现的全部代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract Mapping {mapping(address => uint ) public balances;mapping(address => mapping (address => bool )) public isFriend;function examples() external {balances[msg.sender] = 123;uint bal = balances[msg.sender];uint bal2 = balances[address(1)];balances[msg.sender] = 456;balances[msg.sender] += 456; //默认值 + 546delete balances[msg.sender];//删除会恢复到默认值,而不是说真的删除isFriend[msg.sender][address(this)] = true;}
}
如果你在Remix上运行 那么就会发现有橙色提醒
这段代码是一个 Solidity 合约,展示了以太坊智能合约中的映射数据结构。
以下是每个部分的作用:
`mapping(address => uint) public balances;` 这行代码创建了一个映射(一种键值对数据库),其中地址作为键,对应的值为无符号整数,用于表示账户余额。
同样的概念也适用于 isFriend,它将地址对与表示友谊状态的布尔值进行映射。
该合同有一个名为 examples() 的外部函数,其功能为:
将调用者(msg.sender)的余额设置为 123,使用 balances[msg.sender] = 123; 语句。
通过映射访问该值并将其存储在名为 bal 的新变量中:uint bal = balances[msg.sender];。
然而,当尝试通过 uint bal2 = balances[address(1)]; 获取另一个地址(address(1))的余额时,Solidity 提示声明了一个未使用的局部变量。
错误发生
是因为您声明了一个新变量(bal2),但在代码中任何地方都没有使用它。您可以这样解决:要么删除声明并赋值给 bal2 的那行代码,要么在合约的其他地方实际使用它的值,例如:
无符号整数型变量 bal 被赋值为 balances 中 msg.sender 所对应的值。//...
如果 balances[address(1)] 的值为 0 ,则执行以下操作(即如果地址 1 的余额为零,则执行以下操作)}
这样一来,变量 bal2 就不会再被视为未使用了。
三、映射的注意事项
- 映射中的键值对数量是无限的,但实际存储的键值对数量取决于合约的使用情况.
- 映射中的键是唯一的,但值可以重复.
- 由于区块链的不可变性,映射中的数据一旦写入,就无法被修改或删除,只能通过覆盖或使用
delete
关键字将其恢复为默认值. - 映射的使用会消耗Gas,因此在设计合约时,应尽量优化映射的使用,避免不必要的操作。
四、实际应用
映射在智能合约中有着广泛的应用,例如:
- 代币合约:用于存储每个地址持有的代币数量.
- 去中心化金融(DeFi)合约:用于记录用户的存款、借款等信息.
- 投票合约:用于记录每个地址的投票结果.
- 游戏合约:用于存储玩家的游戏数据,如分数、等级等.
通过合理地使用映射,我们可以构建出高效、可靠的智能合约。
本篇代码为自己结合资料总结,如有错误还请各位随时指出并进行修改~感恩包容理解!