我需要能够在映射中的同一个键下有几个可能的值。今天,Solidity 的映射是单值的:写入一个值会覆盖前一个值(它仍在区块链中,但不能通过合约检索)。我编写了这段代码以获得多值映射:
contract MVM {
struct Bucket {
bool exists;
uint num; // Never decreases: we can only add records, not remove them.
mapping(uint => Record) records;
}
struct Record {
bool exists;
string info;
}
// Do not make it public: the compiler crashes when generating
// accessors https://github.com/ethereum/solidity/issues/633
mapping(string => Bucket) data;
function set(string key, string value) {
if (data[key].exists) {
data[key].records[data[key].num] = Record(true, value);
}
else {
data[key].exists = true;
data[key].records[0] = Record(true, value);
}
data[key].num++;
}
function num_of(string key) returns (uint) {
return data[key].num; // Guaranteed to be initialized as zero?
}
function get(string key, uint index) returns (string) {
if (!data[key].exists || !data[key].records[index].exists) {
throw;
}
return data[key].records[index].info;
}
}
从 geth 控制台使用它的一个例子:
> mvs.set.sendTransaction("foo", "bar", {from:eth.accounts[0], gas: 1000000})
"0x79c52c437a94f3301775acec5639404eff563fce1a99ad097f5db28f109d7ab5"
> mvm.set.sendTransaction("foo", "thing", {from:eth.accounts[0], gas: 1000000})
"0xb26b8d34691b0da5cb48af68933e81b514199f4ed8bd2b557767c8b55da85f50"
> mvm.get.call("foo")
"bar"
> mvm.get.call("foo", 1)
"thing"
> mvm.num_of.call("foo")
2
我的方法有缺陷吗?还是更好的解决方案?