在区块链的世界里,Solidity 是编写以太坊智能合约的热门编程语言。今天,咱们就来深入了解一下 Solidity 中一个超级实用的数据结构 —— 结构体(Structs)。
本文中所有代码均可以在本人GitHub solidity学习代码 中查找到~
资料为本人整理以及结合,如有不对烦请指出~ 感恩包容~
什么是 Solidity 结构体?
官方定义上,结构体是一种能够将多种不同数据类型的变量打包组合在一起的数据格式。想象一下,你要描述一辆汽车,它有品牌型号(这是个字符串,像 “丰田”“特斯拉”)、生产年份(一个数字),还有车主(以太坊中的地址类型)。要是没有结构体,你得分别管理这三个信息,乱糟糟还容易出错。但有了结构体,就像把它们装进一个专属的 “收纳盒”,这个 “收纳盒” 就是咱们定义的 Car 结构体:
struct Car{
string model;
uint year;
address owner;
}
这里,string 用来存车型名字这种文本信息,uint 表示无符号整数,用于记录年份,address 则是以太坊里特有的,用来标识用户独一无二的地址,也就是车主。
结构体的定义和使用
在Solidity中,我们可以通过关键字struct
来定义一个结构体。例如,我们可以定义一个名为Car
的结构体,用于表示汽车的信息:
struct Car {
string model; // 汽车的型号
uint year; // 汽车的年份
address owner; // 汽车的拥有者
}
在这个结构体中,我们定义了三个字段:model
、year
和owner
,分别用于存储汽车的型号、年份和拥有者的地址。字段的类型可以是Solidity支持的任何基本类型,如string
、uint
、address
等。
定义了结构体之后,我们可以在智能合约中创建结构体的实例。例如:
Car public car;
这里我们创建了一个名为car
的公共变量,它的类型是Car
结构体。由于它是公共变量,Solidity会自动生成一个名为car
的getter函数,我们可以通过这个函数来访问car
变量的各个字段。
结构体的初始化和赋值
我们可以使用两种方式来初始化结构体的实例。第一种方式是在声明结构体变量的同时进行初始化,例如:
Car memory toyota = Car("Toyota", 1990, msg.sender);
这里我们使用Car
结构体的构造函数来创建一个名为toyota
的结构体实例,并初始化它的各个字段。memory
关键字表示这个变量是在内存中创建的,而不是在存储中创建的。
第二种方式是先声明结构体变量,然后分别给它的各个字段赋值,例如:
Car memory tesla;
tesla.model = "Tesla";
tesla.year = 2010;
tesla.owner = msg.sender;
这种方式可以让我们在不同的地方对结构体的字段进行赋值,更加灵活。
结构体数组和映射
我们可以将结构体用于数组和映射中,以便存储多个结构体实例。例如:
Car[] public cars;
mapping(address => Car[]) public carsByOwner;
这里我们定义了一个名为cars
的结构体数组,用于存储多个Car
实例。我们还定义了一个名为carsByOwner
的映射,它的键是address
类型,值是Car[]
类型,用于根据汽车拥有者的地址来查找他所拥有的汽车列表。
全部代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
//结构体是能够将很多种变量格式打包组合一起的数据格式
contract Structs {
//叫汽车的结构体
struct Car{
string model;
//字符串,定义了汽车的型号
uint year;
//定义了汽车的年份
address owner;
//定义了汽车的拥有者
}
Car public car;
//结构体大写开头,变量小写开头
Car[] public cars;
mapping (address => Car[]) public carsByOwner;
//结构体类型定义一个映射
function example() external {
Car memory toyota = Car("Toyota",1990,msg.sender) ;
Car memory lambo = Car({model:"Lamborghini",year:1980,owner : msg.sender});
Car memory tesla;
tesla.model = "Tesls";
tesla.year = 2010;
tesla.owner = msg.sender;
//局部变量
cars.push(toyota);
cars.push(lambo);
cars.push(tesla);
//推入和定义一起完成
cars.push(Car("Ferrari",2020,msg.sender));
Car storage _car = cars[0];
_car.model;
_car.year = 1999;
//修改存储中状态变量的值
delete _car.owner;
delete cars[1];
//删除索引为1
}
}
举例子运用
再看个简单的 “学生成绩管理” 合约。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// 学生结构体
struct Student {
string name;
uint[] scores;
}
contract StudentGrades {
Student[] public students;
mapping (string => Student) public studentRecords;
function addStudent(string memory _name, uint[] memory _scores) external {
Student memory newStudent = Student(_name, _scores);
students.push(newStudent);
studentRecords[_name] = newStudent;
}
function updateScore(string memory _name, uint _index, uint _newScore) external {
Student storage student = studentRecords[_name];
student.scores[_index] = _newScore;
}
}
这里定义了 Student 结构体,包含姓名和成绩数组。合约能添加学生信息,还能按索引更新某个学生的某门成绩,是不是很实用?通过结构体,复杂的学生成绩数据管理变得井井有条。
实际应用
结构体在智能合约中有着广泛的应用。例如,在一个去中心化市场中,我们可以使用结构体来表示商品的信息,包括商品的名称、描述、价格、卖家地址等。然后,我们可以将这些结构体实例存储在一个数组或映射中,以便进行商品的添加、查询、购买等操作。
资料为本人整理以及结合,如有不对烦请指出~ 感恩包容~