结构体(Struct)是Solidity中用于定义自定义数据类型的重要特性,可以将多个不同类型的字段组合在一起。本文详细介绍结构体的定义、使用方法和实际应用场景。
一、什么是结构体 一、1 基本概念 结构体(Struct)是一种用户定义的数据类型,可以将多个不同类型的字段组合在一起,形成一个逻辑单元。结构体类似于其他语言中的类或记录类型。
二、2 结构体的特点 可以包含各种类型 可以嵌套结构体 可以包含数组和映射 灵活组合 需要指定storage或memory storage持久化存储 memory临时存储 影响Gas消耗 二、如何定义和使用结构体 三、1 基本定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 pragma solidity ^0.8.0; contract StructExample { struct Person { string name; uint256 age; address wallet; bool isActive; } Person[] public people; mapping(address => Person) public personByAddress; }
可以包含任何类型 字段有名称和类型 可以设置默认值 可以嵌套 四、2 创建结构体实例 1 2 使用命名参数: function addPerson (
string memory _name,
uint256 _age,
address _wallet
1 2 3 4 5 6 7 ) public { Person memory newPerson = Person({ name: _name, age: _age, wallet: _wallet, isActive: true });
1 2 people.push(newPerson); personByAddress[_wallet] = newPerson;
}使用位置参数:solidity
1 2 function addPersonSimple ( Person memory newPerson = Person(_name, _age, _wallet, true );
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ### 五、3 访问和修改 访问字段: function getPerson(uint256 index) public view returns ( string memory, uint256, address, bool ) { Person memory p = people[index]; return (p.name, p.age, p.wallet, p.isActive); } function getPersonName(uint256 index) public view returns (string memory) { return people[index].name; } `修改字段:`solidity function updatePersonAge(uint256 index, uint256 _age) public { people[index].age = _age; } function deactivatePerson(uint256 index) public { people[index].isActive = false; }
六、4 存储位置 1 2 3 4 storage引用: function updateStorage (uint256 index) public { Person storage p = people[index]; p.age = 30 ;
}memory副本:solidity
1 2 3 4 5 function processMemory (uint256 index) public { Person memory p = people[index]; p.age = 30 ; people[index] = p;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ## 三、应用场景 ### 七、1 用户管理 用户信息: contract UserManagement { struct User { uint256 registrationTime; uint256 balance; bool isVerified; } mapping(address => User) public users; address[] public userList; function register(string memory _name) public { require(users[msg.sender].wallet == address(0), "Already registered"); users[msg.sender] = User({ registrationTime: block.timestamp, wallet: msg.sender, balance: 0, isVerified: false }); userList.push(msg.sender); } function verifyUser(address user) public { users[user].isVerified = true; }
八、2 订单系统 1 2 3 4 5 6 7 8 9 10 11 订单信息: contract OrderSystem { struct Order { uint256 orderId; address buyer; address seller; uint256 amount; uint256 timestamp; bool isPaid; bool isShipped; bool isCompleted;
}
1 2 mapping(uint256 => Order) public orders; uint256 public orderCount;
1 2 3 4 5 6 7 8 9 10 11 12 13 function createOrder (address seller, uint256 amount) public returns (uint256) { orderCount++; orders[orderCount] = Order({ orderId: orderCount, buyer: msg.sender, seller: seller, amount: amount, timestamp: block.timestamp, isPaid: false , isShipped: false , isCompleted: false }); return orderCount;
}
1 2 3 4 5 function payOrder (uint256 orderId) public payable { Order storage order = orders[orderId]; require(order.buyer == msg.sender, "Not buyer" ); require(msg.value == order.amount, "Wrong amount" ); require(!order.isPaid, "Already paid" );
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ### 九、3 投票系统 提案和投票: contract VotingSystem { struct Proposal { string description; uint256 voteCount; uint256 deadline; bool executed; mapping(address => bool) hasVoted; } struct Vote { address voter; bool support; } Proposal[] public proposals; mapping(uint256 => Vote[]) public proposalVotes; function createProposal(string memory description, uint256 duration) public { proposals.push(Proposal({ description: description, voteCount: 0, deadline: block.timestamp + duration, executed: false })); function vote(uint256 proposalId, bool support) public { Proposal storage proposal = proposals[proposalId]; require(block.timestamp < proposal.deadline, "Proposal expired"); require(!proposal.hasVoted[msg.sender], "Already voted"); proposal.hasVoted[msg.sender] = true; if (support) { proposal.voteCount++; } proposalVotes[proposalId].push(Vote({ voter: msg.sender, support: support, timestamp: block.timestamp }));
十、4 NFT元数据 1 2 3 4 5 6 7 8 9 NFT信息: contract NFTContract { struct NFT { uint256 tokenId; string imageURI; address creator; uint256 creationTime; uint256 price; bool forSale;
}
1 2 mapping(uint256 => NFT) public nfts; uint256 public tokenCount;
string memory name,
string memory description,
string memory imageURI
1 2 3 4 5 6 7 8 9 10 tokenCount++; nfts[tokenCount] = NFT({ tokenId: tokenCount, name: name, imageURI: imageURI, creator: msg.sender, creationTime: block.timestamp, price: 0, forSale: false });
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ## 四、高级用法 ### 十一、1 嵌套结构体 嵌套定义: contract NestedStruct { struct Address { string street; string city; string country; } Address homeAddress; Address workAddress; } mapping(address => Person) public people; function setPerson( string memory street, string memory city people[msg.sender] = Person({ homeAddress: Address({ street: street, city: city, country: "China" }), workAddress: Address({ street: "", city: "", country: "" }) });
十二、2 结构体数组 1 2 3 4 数组操作: contract StructArray { struct Item { bool available;
}
1 2 3 4 5 function addItem (string memory name, uint256 price) public { items.push(Item({ price: price, available: true }));
1 2 function getAllItems () public view returns (Item[] memory) { return items;
}
1 2 3 4 function getAvailableItems () public view returns (Item[] memory) { uint256 count = 0 ; for (uint256 i = 0 ; i < items.length; i++) { if (items[i].available) count++;
}
1 2 3 4 5 Item[] memory available = new Item[](count); uint256 index = 0; if (items[i].available) { available[index] = items[i]; index++;
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ### 十三、3 结构体映射 映射使用: contract StructMapping { struct Account { uint256 transactionCount; } mapping(address => Account) public accounts; function deposit() public payable { Account storage account = accounts[msg.sender]; account.balance += msg.value; account.transactionCount++; account.isActive = true; } function withdraw(uint256 amount) public { require(account.balance >= amount, "Insufficient balance"); account.balance -= amount; payable(msg.sender).transfer(amount); }
五、最佳实践 十四、1 设计原则 将逻辑相关的数据组合 避免过度嵌套 保持结构清晰 易于理解 1 2 3 4 5 字段命名: // 好的命名 string userName; uint256 registrationDate; address walletAddress;
}
1 2 3 4 5 // 避免模糊命名 struct Data { string s1; uint256 n1; address a1;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ### 十五、2 Gas优化 打包存储: // 优化前:多个存储槽 struct Unpacked { uint256 value1; // 存储槽1 uint256 value2; // 存储槽2 bool flag1; // 存储槽3 bool flag2; // 存储槽4 } // 优化后:打包存储 struct Packed { uint128 value1; // 存储槽1的前128位 uint128 value2; // 存储槽1的后128位 bool flag1; // 存储槽2 bool flag2; // 存储槽2 } `使用memory:`solidity function process(uint256 index) public { Person memory p = people[index]; // 使用memory // 处理逻辑 // 如果需要修改,最后写回 }
十六、3 安全考虑 1 2 3 4 输入验证: function addPerson (string memory _name, uint256 _age) public { require(bytes(_name).length > 0 , "Name cannot be empty" ); require(_age > 0 && _age < 150 , "Invalid age" );
1 2 people.push(Person({ }));
边界检查:solidity
1 2 function updatePerson (uint256 index, uint256 _age) public { require(index < people.length, "Index out of bounds" );
}
## 六、总结
结构体是Solidity中组织和管理复杂数据的重要工具。关键要点:
定义使用:
- 组合多个字段
- 支持嵌套和复杂类型
- 需要指定存储位置
- 灵活的数据组织
应用场景:
- 用户管理
- 订单系统
- 投票系统
- NFT元数据
最佳实践:
- 合理设计结构
- 优化Gas消耗
- 验证输入数据
- 提高代码可读性
通过合理使用结构体,可以更好地组织数据,提高代码的可读性和可维护性,构建更复杂的智能合约应用。
本文标题: Solidity结构体类型
发布时间: 2024年06月27日 00:00
最后更新: 2025年12月30日 08:54
原始链接: https://haoxiang.eu.org/2d1903cd/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!