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