本文介绍了Solidity中的结构体(struct),讲解了结构体的定义、创建,以及如何在智能合约中使用。展示了如何声明和初始化结构体的不同方法,以及如何将结构体映射。
在Solidity中有不同的基本数据类型,如 uint(无符号整数)、bool 和 string,但是作为一个区块链开发者,你可能需要一个可以自定义的灵活数据类型。struct 是Solidity中的一种数据结构格式,允许将不同数据类型的变量组合成一个变量或用户定义的类型。
本文将向你介绍Solidity中的结构体,演示它们的功能和工作原理。最后,我们将解释如何使用结构体来创建更强大的智能合约。
结构体是Solidity中的一种创新的数据结构格式,允许将不同数据类型的变量组合成一个变量或用户定义的类型。 一旦数据类型被分组到结构体中,结构体的名称就代表结构体内的变量子集。
可以将结构体视为一种容器,里面包含不同类型的对象,因此当你移动这个容器时,容器内的所有项目也会随之移动。因此,当Solidity开发者声明或调用结构体的名称时,结构体会根据其内部的数据类型做出响应。
以下是一个Solidity结构体的示例:
contract MyVault{
struct Vault{
address creator;
string name;
address users;
uint amount;
}
}
上面的结构体示例包含了address creator、string name、address users和uint amount的变量。
本节将向你展示如何在Solidity中定义和创建结构体的示例代码。我们还将演示结构体声明的两种选择。最后,我们将展示如何导入和初始化结构体。
结构体代码类似于Javascript中的对象声明。尽管外观相似,但语法有所不同。Solidity结构体始终采用以下格式:
struct name{
string theWord;
uint theFigure;
bool polar;
}
以下是如何定义和创建Solidity结构体的步骤:
通过编写struct关键字创建结构体,这告诉Solidity编译器前面的类型是用户自定义类型
命名结构体,这将与结构体中打包的变量进行共同引用
使用花括号,因为使用任何其他形式的括号,如方括号或圆括号都将无法编译
如果你不使用花括号,你将在Remix中生成ParserError消息。
未使用花括号的解析错误消息。
在上面的示例中,它们是string theWord、uint theFigure和bool polarData。这是你声明结构体子集的地方。在智能合约中声明结构体后,我们可以在代码的后续中调用结构体名称。
只使用花括号
每个结构体成员末尾使用分号
如果声明的数据类型和输入的变量不匹配,Solidity将抛出错误
智能合约可以包含多个结构体,通过它们的关键字区分
你可以在合约内或合约外声明结构体。知道在哪里声明Solidity结构体取决于你的需求。让我们看看两种结构体声明的选项。
pragma solidity ^0.8.16;
// 这是一个在合约外声明的结构体
struct floorOverlay{
string carpet;
string rug;
}
在上面的示例中,结构体_floorOverlay_是在智能合约外声明的,代码库中的所有合约都可以调用它。最好在智能合约外声明结构体,以创建更适用于所有合约的结构体,而不是仅限于某个合约,其可能有特定的结构体。
此外,如果希望智能合约访问相同的集合结构体,可以在_pragma_后立即声明,而不是在每个智能合约中分别创建结构体。
结构体_carpet_在智能合约内,因此该结构体的功能仅限于当前合约。没有其他合约可以调用它的名称。
contract CarpetContract{
// 这个结构体在此合约内声明
struct carpet{
string name;
uint length;
uint breadth;
bool shipped;
}
}
结构体可以从一个智能合约导入到另一个合约,帮助开发者节省时间并创建可重用的代码。以下是两个智能合约的示例,其中一个创建了结构体,另一个将导入它。
pragma solidity ^0.8.16;
// 在Remix上将此合约保存为“struct”
contract A{
struct vaccine{
string name;
uint id;
bool vaccinated;
}
}
在导入时,你应该避免的错误是:第二个合约的名称应与你想要导入的结构体名称相同。否则,Solidity编译器将无法识别它,导致错误。
pragma solidity ^0.8.16;
import "./struct.sol";
contract Vaccine{
// 将其存储为状态变量
Vaccine public drug;
// 接下来定义更多状态变量和函数
}
即使你已声明并创建结构体,但在各种Solidity函数中使用它,你仍需为其分配某个初始值。你可以通过以下3种方法初始化结构体:(i) 键值对方法,(ii) 定义和更新方法,(iii) 使用括号参数。
在此方法中,你将选择结构体中的每种键类型,并为其分配值。
Vaccine memory tetanus = Vaccine({vaccinated: false, name: "Tetanus", id: 3});
此方法的语法并不严格,你可以选择不按照结构体中类型的顺序。
此初始化方法的语法是,你必须先输入一个变量来存储结构体,然后使用该变量来访问和命名结构体的每个成员。以下代码为说明:
Vaccine memory polio
polio.name = "Polio";
polio.id = 3;
polio.vaccinated = true;
请注意,大多数开发者不会使用此方法,因为它较长。
如果你想使用此方法,必须调用结构体的名称,存储其内存,并以顺序给结构体的成员赋值。以下是一个示例:
Vaccine memory measles = Vaccine("Measles", 2, false);
在此,“measles”是存储此初始化的变量,我们还按结构体中列出的内容声明了参数。请记住要在括号内用撇号包含声明的名称,以便Solidity编译器能够识别它。
本节展示了使用Solidity跟踪智能合约中用户信息的用例。结构体在该用例中进行了映射。
结构体可以作为值类型在Solidity中被映射,以便跟踪与结构体的任何成员相关的信息。 请看以下代码示例:
pragma solidity ^0.8.16;
contract MapStructs{
struct DaoMembers{
address owner;
string name;
string guild;
bool voted;
}
mapping(address => DaoMembers) members;
mapping (bool => mapping(address => DaoMembers)) memberStatus;
}
在这个合约中,特定DAO每个成员的详细信息被分类。我们创建了两个映射:一个是简单映射,另一个是嵌套映射。
在简单映射中,我们映射每个成员的地址到结构体中,以方便查找特定成员。此外,使用嵌套映射可以更方便地跟踪DAO成员的地址以及他们是否投票。
因为映射总是采用键类型 => 值类型的语法,所以结构体必须始终声明为值类型,而不是键类型。否则,你将收到错误信息。
Remix错误显示如果尝试将结构体声明为键类型会发生什么。
Solidity中的结构体允许开发者创建适合其构建目标的自定义类型。这些自定义类型类似于容器,容纳了其他相关的数据类型。
- 原文链接: alchemy.com/overviews/so...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!