背景
通过学习Solidity,然后输出文章检验自己的学习成果github仓库
基础知识
- 创建映射(Mapping)的语法是
mapping(KeyType KeyName? => ValueType ValueName?) VariableName,也可以写成mapping(KeyType => ValueType) - 新增
Key Value的语法是Var[Key] = Value,其中Var是映射变量名,Key和Value对应新增的键值对 - 删除
Key Value的语法是delete Var[Key],其中Var是映射变量名,Key是要删除的键 - 映射(Mapping)类似于数据结构中的
哈希表 - 映射(Mapping)的细节
KeyType可以是Solidity的值类型,bytes,string和合约类型,不可以使用自定义结构体ValueType可以是任何类型包含映射(Mapping)或者数组或者结构体- 映射(Mapping)的存储数据位置必须是storage,可以用于存储状态变量或函数内的存储引用或库函数的参数
- 映射(Mapping)不能作为函数的参数或返回结果
- 映射(Mapping)不能被遍历
- 若映射(Mapping)声明为
public,那么Solidity会自动给你创建一个getter函数,可以通过Key来查询对应的Value
- 映射(Mapping)原理
- 映射(Mapping)在实际的初始化过程中,创建每个可能的Key,并将其映射到字节形式全是零的值:
一个类型的默认值 - 在映射(Mapping)中,实际上并不存储Key的值,而是存储它的
keccak256的哈希值,从而便于查询实际的值 - 映射(Mapping)中不存储
length的信息
- 映射(Mapping)在实际的初始化过程中,创建每个可能的Key,并将其映射到字节形式全是零的值:
例子
该例子是使用映射(Mapping)的例子
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Mapping {
mapping(address => uint) public map;
mapping(ValueContract => uint) public contractMap;
function getMap(address _addr) public view returns (uint){
return map[_addr];
}
function setMap(address _addr, uint _i) public {
map[_addr] = _i;
}
function removeMap(address _addr) public {
delete map[_addr];
}
function getContractMap(ValueContract _addr) public view returns (uint){
return contractMap[_addr];
}
function setContractMap(ValueContract _addr, uint _i) public {
contractMap[_addr] = _i;
}
function removeContractMap(ValueContract _addr) public {
delete contractMap[_addr];
}
}
contract NestedMapping {
mapping(address => mapping(uint => bool)) public nested;
function get(address _addr, uint _i) public view returns (bool){
return nested[_addr][_i];
}
function set(address _addr, uint _i, bool _boo) public {
nested[_addr][_i] = _boo;
}
function remove(address _addr, uint _i) public {
delete nested[_addr][_i];
}
}
contract ValueContract {
uint public value;
constructor(uint _value) {
value = _value;
}
}
程序解析
ValueContract 合约
contract ValueContract {}
- 声明了一个叫
ValueContract的空合约
Mapping 合约
mapping(address => uint) public map;
mapping(ValueContract => uint) public contractMap;
- 声明了
map和contractMap,分别从 address 映射到 uint 和 ValueContract 映射到 uint map和contractMap声明为public,其实会自动生成get函数
function getMap(address _addr) public view returns (uint){
return map[_addr];
}
function getContractMap(ValueContract _addr) public view returns (uint){
return contractMap[_addr];
}
- 映射(Mapping)总是返回一个值
- 如果这个值从没被设置过,则将会返回
默认值
function setMap(address _addr, uint _i) public {
map[_addr] = _i;
}
function getContractMap(ValueContract _addr) public view returns (uint){
return contractMap[_addr];
}
- 更新这个地址或这个合约类型映射的值
function removeMap(address _addr) public {
delete map[_addr];
}
function removeContractMap(ValueContract _addr) public {
delete contractMap[_addr];
}
- 重置这个值到默认值
NestedMapping 合约
mapping(address => mapping(uint => bool)) public nested;
- 嵌套映射 address 到 另一个mapping
function get(address _addr, uint _i) public view returns (bool){
return nested[_addr][_i];
}
- 你可以从嵌套映射中得到值,即使没有初始化
function set(address _addr, uint _i, bool _boo) public {
nested[_addr][_i] = _boo;
}
- 设置这个地址和这个整数型的值
function remove(address _addr, uint _i) public {
delete nested[_addr][_i];
}
- 重置这个值到
默认值