智能合约语言 Solidity 教程 - 结构体与映射
智能合约语言 Solidity 教程 - 结构体with映射
结构体(Structs)
Solidity提供struct来定义自定义类型,自定义的类型是引用类型。
pragma solidity ^0.4.11;
contract CrowdFunding {
// 定义一个包含两个成员的新类型
struct Funder {
address addr;
uint amount;
}struct Campaign {
address beneficiary;
uint fundingGoal;
uint numFunders;
uint amount;
mapping (uint => Funder) funders;
}uint numCampaigns;
mapping (uint => Campaign) campaigns;function newCampaign(address beneficiary, uint goal) public returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID 作为一个变量返回
// 创建一个结构体实例,存储在storage ,放入mapping里
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
}function contribute(uint campaignID) public payable {
Campaign storage c = campaigns[campaignID];
// 用mapping对应项创建一个结构体引用
// 也可以用 Funder(msg.sender, msg.value) 来初始化.
c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
c.amount += msg.value;
}function checkGoalReached(uint campaignID) public returns (bool reached) {
Campaign storage c = campaigns[campaignID];
if (c.amount < c.fundingGoal)
return false;
uint amount = c.amount;
c.amount = 0;
c.beneficiary.transfer(amount);
return true;
}
}
上面是一个简化版的众筹合约,但它可以让我们理解structs的基础概念,struct可以用于映射和数组中作为元素。其本身也可以包含映射和数组等类型。
- 不能在结构体中嵌套自身,因为这会导致结构体的大小无法确定。
- 你可以将结构体用作映射的值类型成员,这样可以在映射中存储结构体的实例。
- 在函数中,如果你将结构体分配给一个局部变量,实际上是将一个指向结构体在存储中的位置的引用复制到了该局部变量中,所以对局部变量的修改会反映到原始结构体上。
- 你也可以直接访问结构体的成员来修改值,而无需显式创建局部变量,例如使用
campaigns[campaignID].amount = 0
这种方式来更新结构体成员的值。
映射(Mappings)
映射类型,一种键值对的映射关系存储结构。定义方式为mapping(_KeyType => _KeyValue)。键类型允许除映射、变长数组、合约、枚举、结构体外的几乎所有类型()。值类型没有任何限制,可以为任何类型包括映射类型。
映射可以被视作为一个哈希表,所有可能的键会被虚拟化的创建,映射到一个类型的默认值(二进制的全零表示)。在映射表中,并不存储键的数据,仅仅存储它的keccak256哈希值,这个哈希值在查找值时需要用到。正因为此,映射是没有长度的,也没有键集合或值集合的概念。
- 映射类型通常用作状态变量,或者在内部函数中作为storage类型的引用。它们用于存储键值对数据。
- 通过将映射标记为
public
,你可以使Solidity自动生成一个访问器(getter方法)。通过提供一个键作为参数,你可以使用这个访问器来获取映射中对应键的值。 - 映射的值类型也可以是映射。在访问时,你需要提供嵌套映射的键,以便逐级访问内部映射的值,重复这个过程。这允许你建立更复杂的数据结构。
来看一个例子:
pragma solidity ^0.4.0;
contract MappingExample {
mapping(address => uint) public balances;function update(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}contract MappingUser {
function f() public returns (uint) {
MappingExample m = new MappingExample();
m.update(100);
return m.balances(this);
}
}
Please specify source if reproduced智能合约语言 Solidity 教程 - 结构体与映射 | Dexnav 区块链导航网