多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 映射/字典(mappings) `映射`或字典类型,一种键值对的映射关系存储结构。定义方式为`mapping(_KeyType => _KeyValue)`。键的类型允许除`映射`外的所有类型,如数组,合约,枚举,结构体。值的类型无限制。 `映射`可以被视作为一个哈希表,其中所有可能的键已被虚拟化的创建,被映射到一个默认值(二进制表示的零)。但在映射表中,我们并不存储键的数据,仅仅存储它的`keccak256`哈希值,用来查找值时使用。 因此,`映射`并没有长度,键集合(或列表),值集合(或列表)这样的概念。 `映射`类型,仅能用来定义`状态变量`,或者是在内部函数中作为`storage`类型的引用。引用是指你可以声明一个,如`var storage mappVal`的用于存储状态变量的引用的对象,但你没办法使用非状态变量来初始化这个引用。 可以通过将`映射`标记为`public`,来让Solidity创建一个访问器。要想访问这样的`映射`,需要提供一个键值做为参数。如果`映射`的值类型也是`映射`,使用访问器访问时,要提供这个`映射`值所对应的键,不断重复这个过程。下面来看一个例子: ``` contract MappingExample{ mapping(address => uint) public balances; function update(uint amount) returns (address addr){ balances[msg.sender] = amount; return msg.sender; } } ``` 由于调试时,你不一定方便知道自己的发起地址,所以把这个函数,略微调整了一下,以在调用时,返回调用者的地址。编译上述合同后,可以先调用`update()`,执行成功后,查看调用信息,能看到你更新的地址,这样再查一下这个地址的在映射里存的值。 如果你想通过合约进行上述调用。 ``` pragma solidity ^0.4.0; //file indeed for compile //may store in somewhere and import contract MappingExample{ mapping(address => uint) public balances; function update(uint amount) returns (address addr){ balances[msg.sender] = amount; return msg.sender; } } contract MappingUser{ address conAddr; address userAddr; function f() returns (uint amount){ //address not resolved! //tringing conAddr = hex"0xf2bd5de8b57ebfc45dcee97524a7a08fccc80aef"; userAddr = hex"0xca35b7d915458ef540ade6068dfe2f44e8fa733c"; return MappingExample(conAddr).balances(userAddr); } } ``` `映射`并未提供迭代输出的方法,可以自行实现一个数据结构。参见[iterable mapping](https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol)。