当前位置: 首页 > news >正文

solidity基础 -- 映射

       在区块链的智能合约开发领域,Solidity 作为以太坊上最主流的编程语言之一,拥有诸多强大特性助力开发者构建复杂且高效的去中心化应用。其中,映射(Mapping)是一个极为关键的数据结构,它为合约中的数据存储与检索提供了便捷、高效的方式。

        本篇代码为自己结合资料总结,如有错误还请各位随时指出并进行修改~感恩包容理解!

        另所有本篇以及以前出现的代码均可以在本人GitHub GitHub - solidity学习代码 上找到

一、映射的基础概念

       在 Solidity 中,映射如同一个神奇的 “账本”,能够以键值对的形式存储数据。以代码中的 mapping(address => uint ) public balances; 为例,它创建了一个从以太坊地址(address 类型)到无符号整数(uint 类型)的映射关系,通俗来讲,就是可以针对不同的以太坊地址记录对应的余额数值。这就像是现实世界银行给每个客户设立账户并记录存款余额,只不过这里的 “账户” 是以太坊地址,“余额” 是合约中所关心的各种数值信息。

       映射是一种键值对的数据结构,类似于传统编程语言中的哈希表或字典。在Solidity中,映射用于将一个值(键)映射到另一个值(值)。其基本语法如下:

mapping(_KeyType => _ValueType) _mappingName;
  • _KeyType:键的类型,可以是任何基本类型,如addressuintbytes32等,但不能是复杂类型如结构体或数组.
  • _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)合约:用于记录用户的存款、借款等信息.
  • 投票合约:用于记录每个地址的投票结果.
  • 游戏合约:用于存储玩家的游戏数据,如分数、等级等.

通过合理地使用映射,我们可以构建出高效、可靠的智能合约。

本篇代码为自己结合资料总结,如有错误还请各位随时指出并进行修改~感恩包容理解!

http://www.lryc.cn/news/518481.html

相关文章:

  • Angular 11课程实践:构建高效单页应用的支持代码
  • 测试用例颗粒度说明
  • ESP32 IDF VScode出现头文件“无法打开 源 文件 ”,并有红色下划线警告
  • Windows安装ES单机版设置密码
  • Linux Docker
  • MSE学习
  • 0-基于蚁群优化和带注意力机制的循环神经网络的新型混合算法用于解决旅行商问题(HAL science)(完)
  • MIUI显示/隐藏5G开关的方法,信号弱时开启手机Wifi通话方法
  • 挑战20天刷完leecode100
  • Java列表示例
  • Objective-C语言的网络编程
  • 安卓OCR使用(Google ML Kit)
  • 《机器学习》——贝叶斯算法
  • 【博主推荐】 Microi吾码开源低代码平台,快速建站,提高开发效率
  • 网站自动签到
  • C 语言奇幻之旅 - 第16篇:C 语言项目实战
  • 项目实战——使用python脚本完成指定OTA或者其他功能的自动化断电上电测试
  • 04、Redis深入数据结构
  • 【MySQL学习笔记】MySQL的索引
  • 利用ArcGIS快速准确地统计出地块的现状容积率
  • C++类的引入
  • 【跨域问题】
  • “深入浅出”系列之FFmpeg:(1)音视频开发基础
  • Springboot3.4整合jsp
  • CSS:背景样式、盒子模型与文本样式
  • 算法:线性查找
  • 【计算机网络】什么是网关(Gateway)?
  • 20250106面试
  • Java 分布式锁:Redisson、Zookeeper、Spring 提供的 Redis 分布式锁封装详解
  • 智能汽车的数字钥匙安全