Solidity - 使用数组的正确方法
Solidity - Correct way to use arrays
你好,我是 Solidity 的新手,我想建立一个可以创建船舶、显示所有船舶(我使用“分页”)、显示用户的所有船舶以及摧毁船舶的联系人。
我想通过良好的实践来编写正确的代码。这就是为什么我发布我的“解决方案”以从数组中“删除”一个值而不遍历数组。
我所做的是,创建船舶数组,用户拥有的所有船舶索引数组的映射,以及用户数组的映射,以便轻松找到用户索引数组索引中的位置。
我的问题是“deleteShip”函数是否会因为多个事务(应该是原子的)而中断?如何?正确的做法是什么?
struct StructureShip {
address owner;
string name;
uint256 price;
bool sale;
}
StructureShip[] private ships;
mapping(address => uint256[]) private ships_by_user;
mapping(uint256 => uint256) private ships_by_user_index;
uint256[] private ships_sale;
mapping(uint256 => uint256) private ships_sale_index;
function createShip(string memory _ship_name) public {
StructureShip memory _ship = StructureShip({
name: _ship_name,
owner: msg.sender,
price: 0,
sale: false
});
ships.push(_ship);
ships_by_user[msg.sender].push(ships.length - 1);
ships_by_user_index[ships.length - 1] =
ships_by_user[msg.sender].length -
1;
}
function getShips(uint _page)
external
view
returns (StructureShip[10] memory)
{
StructureShip[10] memory _ships;
for (uint index = (_page - 1) * 10; index < _page * 10; index++ ) {
if (ships.length == index) {
break;
}
_ships[index - (_page - 1) * 10] = ships[index];
}
return _ships;
}
function getShipsByUser(address _user, uint256 _page)
external
view
returns (StructureShip[10] memory)
{
StructureShip[10] memory _ships;
for (uint index = (_page - 1) * 10; index < _page * 10; index++ ) {
if (ships_by_user[_user].length == index) {
break;
}
_ships[index - (_page - 1) * 10] = ships[ships_by_user[_user][index]];
}
return _ships;
}
function deleteShip(uint256 _id) public onlyCaptain(_id) {
//borrar index de usuario
ships_by_user[ships[_id].owner][
ships_by_user_index[_id]
] = ships_by_user[ships[_id].owner][
ships_by_user[ships[_id].owner].length - 1
];
ships_by_user_index[_id] = ships_by_user[ships[_id].owner].length - 1;
ships_by_user[ships[_id].owner].pop();
//reubicar ultimo barco
ships_by_user[ships[ships.length - 1].owner][
ships_by_user_index[ships.length - 1]
] = _id;
ships_by_user_index[ships.length - 1] = ships_by_user_index[_id];
//borrar publicación de venta
if (ships[_id].sale) {
ships_sale_index[ships_sale[ships_sale.length - 1]] = _id;
ships_sale[ships_sale_index[_id]] = ships_sale[
ships_sale.length - 1
];
ships_sale.pop();
}
//reubicar publicación de venta ultimo barco
if (ships[ships.length - 1].sale) {
ships_sale_index[_id] = ships_sale_index[ships.length - 1];
ships_sale[ships_sale_index[ships.length - 1]] = _id;
}
//borrar ultimo barco vacío
ships[_id] = ships[ships.length - 1];
ships.pop();
}
}
每笔交易都按时间顺序开采(即处理并添加到区块中),顺序由获胜矿工决定。
因此,当第一笔销毁船舶的交易被执行和开采时,合约状态发生变化。然后下一笔交易被处理和挖掘,状态再次转移,准备通过后续交易进行下一次状态变化。
有关此主题的更多讨论,请参阅以下内容:
https://ethereum.stackexchange.com/questions/43895/update-the-same-variable-in-parallel
https://ethereum.stackexchange.com/questions/1405/what-is-the-order-and-concurrency-behavior-of-multiple-calls-to-a-contract-in-a
你好,我是 Solidity 的新手,我想建立一个可以创建船舶、显示所有船舶(我使用“分页”)、显示用户的所有船舶以及摧毁船舶的联系人。
我想通过良好的实践来编写正确的代码。这就是为什么我发布我的“解决方案”以从数组中“删除”一个值而不遍历数组。
我所做的是,创建船舶数组,用户拥有的所有船舶索引数组的映射,以及用户数组的映射,以便轻松找到用户索引数组索引中的位置。
我的问题是“deleteShip”函数是否会因为多个事务(应该是原子的)而中断?如何?正确的做法是什么?
struct StructureShip {
address owner;
string name;
uint256 price;
bool sale;
}
StructureShip[] private ships;
mapping(address => uint256[]) private ships_by_user;
mapping(uint256 => uint256) private ships_by_user_index;
uint256[] private ships_sale;
mapping(uint256 => uint256) private ships_sale_index;
function createShip(string memory _ship_name) public {
StructureShip memory _ship = StructureShip({
name: _ship_name,
owner: msg.sender,
price: 0,
sale: false
});
ships.push(_ship);
ships_by_user[msg.sender].push(ships.length - 1);
ships_by_user_index[ships.length - 1] =
ships_by_user[msg.sender].length -
1;
}
function getShips(uint _page)
external
view
returns (StructureShip[10] memory)
{
StructureShip[10] memory _ships;
for (uint index = (_page - 1) * 10; index < _page * 10; index++ ) {
if (ships.length == index) {
break;
}
_ships[index - (_page - 1) * 10] = ships[index];
}
return _ships;
}
function getShipsByUser(address _user, uint256 _page)
external
view
returns (StructureShip[10] memory)
{
StructureShip[10] memory _ships;
for (uint index = (_page - 1) * 10; index < _page * 10; index++ ) {
if (ships_by_user[_user].length == index) {
break;
}
_ships[index - (_page - 1) * 10] = ships[ships_by_user[_user][index]];
}
return _ships;
}
function deleteShip(uint256 _id) public onlyCaptain(_id) {
//borrar index de usuario
ships_by_user[ships[_id].owner][
ships_by_user_index[_id]
] = ships_by_user[ships[_id].owner][
ships_by_user[ships[_id].owner].length - 1
];
ships_by_user_index[_id] = ships_by_user[ships[_id].owner].length - 1;
ships_by_user[ships[_id].owner].pop();
//reubicar ultimo barco
ships_by_user[ships[ships.length - 1].owner][
ships_by_user_index[ships.length - 1]
] = _id;
ships_by_user_index[ships.length - 1] = ships_by_user_index[_id];
//borrar publicación de venta
if (ships[_id].sale) {
ships_sale_index[ships_sale[ships_sale.length - 1]] = _id;
ships_sale[ships_sale_index[_id]] = ships_sale[
ships_sale.length - 1
];
ships_sale.pop();
}
//reubicar publicación de venta ultimo barco
if (ships[ships.length - 1].sale) {
ships_sale_index[_id] = ships_sale_index[ships.length - 1];
ships_sale[ships_sale_index[ships.length - 1]] = _id;
}
//borrar ultimo barco vacío
ships[_id] = ships[ships.length - 1];
ships.pop();
}
}
每笔交易都按时间顺序开采(即处理并添加到区块中),顺序由获胜矿工决定。
因此,当第一笔销毁船舶的交易被执行和开采时,合约状态发生变化。然后下一笔交易被处理和挖掘,状态再次转移,准备通过后续交易进行下一次状态变化。
有关此主题的更多讨论,请参阅以下内容:
https://ethereum.stackexchange.com/questions/43895/update-the-same-variable-in-parallel https://ethereum.stackexchange.com/questions/1405/what-is-the-order-and-concurrency-behavior-of-multiple-calls-to-a-contract-in-a