美文网首页
6. Solidity:引用类型变量:映射

6. Solidity:引用类型变量:映射

作者: 泡泡龙吐泡泡 | 来源:发表于2023-09-26 08:59 被阅读0次

6.1 映射的声明

映射(mapping)是Solidity中的哈希表,实现通过key值查询对应的Value,例如:通过调用者的地址查询其余额。声明映射的格式为:mapping(_keyType => _valueType)

示例代码:

    // 声明映射   (钱包地址的余额)
    mapping (address => uint) public balances;
    // 声明嵌套映射    (两个地址是否为朋友关系)
    mapping (address => mapping (address => bool)) public isFriend;

6.2 映射相关操作

映射的设置、查询、删除操作示例:


    // ***************************映射***************************
    // 设置
    function setBalance(uint _balance) external {
        balances[msg.sender] = _balance;
    }

    // 查询
    function getBalance() external view returns (uint) {
        return balances[msg.sender];
    } 

    // 删除
    function deleteBalance() external {
        delete balances[msg.sender];    // 余额设置为默认值:0
    }

    // ***************************嵌套映射***************************
    // 设置
    function setFriend() external {
        // 设置合约地址为调用者的朋友
        isFriend[msg.sender][address(this)] = true;
    }

    // 查询
    function getFriend() external view returns (bool) {
        return isFriend[msg.sender][address(this)];
    }

    // 删除
    function deleteFriend() external {
        delete isFriend[msg.sender][address(this)];
    }

Solidity中所有数据都有默认值,查询不存在的(未赋值的)key对应的value,并不会报错,而会返回value类型的默认值。
例如,在没有调用设置方法(setBalance()、setFriend())的情况下,调用查询方法getBalance()会返回uint类型的默认值0,调用查询方法getFriend()会返回bool类型的默认值false。

6.3 映射的规则

  • 规则一:key值类型只能为solidity中默认的类型,比如uint、address等,不能使用自定义的结构体。value可以为自定义的结构体。
  • 规则二:映射存储位置必须为storage,因此可以用于状态变量、函数中的storage变量、library/internal/private函数的参数和返回值,不能用于其他函数的参数或者返回值。

Types containing (nested) mappings can only be parameters or return variables of internal or library functions.

  • 规则三:如果映射声明为public,那么solidity会自动给你创建一个getter函数,可以通过Key来查询对应的Value。

6.4 映射的原理

  • 原理1:映射不储存任何键(Key)的信息(例如哪些Key被使用),也没有length的信息。

  • 原理2:映射使用keccak256(key)当成offset存取value。

  • 原理3:因为Ethereum会定义所有未使用的空间为0,所以未赋值(Value)的键(Key)初始值都是各个type的默认值,如uint的默认值是0。

6.5 可遍历映射

根据原理一,映射不储存任何键(Key)的信息(例如哪些Key被使用),也没有length的信息,因此solidity中映射类型本身不可遍历。
可以通过以下方式实现可遍历映射:

  • 定义一个映射(_key=>bool映射),记录key是否存在于映射中。
  • 定义一个数组(_key值数组),记录所有存在的(被使用的)key。

一个可遍历映射示例:

contract IterableMapping {
    mapping (address => uint) public balances;
    // 记录某一个地址(key)是否存在于映射中
    mapping (address => bool) public inserted;
    // 记录所有存在的地址(key)
    address[] public keys;

    // 设置键值对
    function set(address _key, uint _value) external {
        // 设置键值对
        balances[_key] = _value;
        // 判断键值对在设置前是否存在
        if (!inserted[_key]) { // false
            inserted[_key] = true;
            keys.push(_key);
        }
    }

    // 根据索引获取value
    function get(uint _i) external view returns (uint) {
        require(_i < keys.length, "index out of range");
        return balances[keys[_i]];
    }

    // 余额汇总
    function getTotal() external view returns (uint sum) {
        for (uint i = 0;i < keys.length;i++) {
            sum += balances[keys[i]];
        }
    }
}

相关文章

网友评论

      本文标题:6. Solidity:引用类型变量:映射

      本文链接:https://www.haomeiwen.com/subject/tszfbdtx.html