【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory)

本文主要是介绍【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、前言

看了一些区块链的教程,论文,在网上刚刚找到了一个项目实战,CryptoZombies。

如果你想了解更多有关于机器学习、深度学习、区块链、计算机视觉等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

二、 永久存储变量(Storage)和 临时存储变量(Memory)

1、讲解

我们在代码中会经常需要存储变量,有些变量是我们永久存储的,有些则是临时存储的,在solidity中,也是如此。solidity有两种存储变量:

1.storage 变量是永久存储在区块链中的变量

2.memory 变量是临时存储在区块链中的变量,当外部函数对某合约调用完成时,内存型变量即被移除。

当然,大多数情况下,我们很少会用到,solidity会自动处理,状态变量(在函数外声明的变量)默认为storage类型的变量,即永久存储,状态变量会永久写入区块链。在函数内部声明的变量,是memory类型的变量,函数调用结束就会消失。

除了系统默认之外,我们也可以自己手动声明,一般常用于我们处理函数内部的结构体structs和数组arrays

例如下面的示例。

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {// Sandwich mySandwich = sandwiches[_index];}
}

上面添加注释的这句话,看上去很直接,不过 Solidity 会给出警告 ,应该明确在这里定义 `storage` 或者 `memory`。 正确写法如下:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {// Sandwich mySandwich = sandwiches[_index];Sandwich storage mySandwich = sandwiches[_index];mySandwich.status = "Eaten!";}
}

其中 `mySandwich` 是指向 `sandwiches[_index]`的指针 ,这将永久把 `sandwiches[_index]` 变为区块链上的存储。

如果你只想要一个副本,可以这样写:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {Sandwich memory anotherSandwich = sandwiches[_index + 1];anotherSandwich.status = "Eaten!";}
}

这样 `anotherSandwich` 就仅仅是一个内存里的副本了 ,后续操作也仅仅修改临时变量,对 `sandwiches[_index + 1]` 没有任何影响。

如果想把副本的改动保存回区块链存储,可以这样做:

contract SandwichFactory {struct Sandwich {string name;string status;}Sandwich[] sandwiches;function eatSandwich(uint _index) public {Sandwich memory anotherSandwich = sandwiches[_index + 1];anotherSandwich.status = "Eaten!";sandwiches[_index + 1] = anotherSandwich;}
}

所以我们在具体使用过程中,也需要考虑使用storge还是memory。

2、实战1

1.要求

当一个僵尸猎食其他生物体时,它自身的DNA将与猎物生物的DNA结合在一起,形成一个新的僵尸DNA。

1.创建一个名为 feedAndMultiply 的函数。 使用两个参数:_zombieId( uint类型 )和_targetDna (也是 uint 类型)。设置属性为 public 的。

2.我们不希望别人用我们的僵尸去捕猎。 首先,我们确保对自己僵尸的所有权。 通过添加一个require 语句来确保 msg.sender 只能是这个僵尸的主人(类似于我们在 createRandomZombie 函数中做过的那样)。

3.为了获取这个僵尸的DNA,我们的函数需要声明一个名为 myZombie 数据类型为Zombie的本地变量(这是一个 storage 型的指针)。 将其值设定为在 zombies 数组中索引为_zombieId所指向的值。

到目前为止,包括函数结束符 } 的那一行, 总共4行代码。

2.代码

pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";contract ZombieFeeding is ZombieFactory {// Start herefunction feedAndMultiply(uint _zombieId, uint _targetDna) public {require(msg.sender == zombieToOwner[_zombieId]);Zombie storage myZombie = zombies[_zombieId];}}

 

3、实战2

1.要求

1.首先确保 _targetDna 不长于16位。要做到这一点,设置 _targetDna 为 _targetDna % dnaModulus ,并且只取其最后16位数字。

2.接下来为函数声明一个名叫 newDna 的 uint类型的变量,并将其值设置为 myZombie的 DNA 和 _targetDna 的平均值(如上例所示)。

注意:可以用 myZombie.name 或 myZombie.dna 访问 myZombie 的属性

3.一旦计算出新的DNA,再调用 _createZombie 就可以生成新的僵尸了。如果忘记调用这个函数所需要的参数,可以查看 zombiefactory.sol 选项卡。请注意,需要先给它命名,把新的僵尸的名字设为NoName - 也可以编写一个函数来更改僵尸的名字。

2.代码

pragma solidity >=0.5.0 <0.6.0;import "./zombiefactory.sol";contract ZombieFeeding is ZombieFactory {function feedAndMultiply(uint _zombieId, uint _targetDna) public {require(msg.sender == zombieToOwner[_zombieId]);Zombie storage myZombie = zombies[_zombieId];// start here_targetDna = _targetDna%dnaModulus;uint newDna = (myZombie.dna + _targetDna) / 2;_createZombie("NoName", newDna);}}

这篇关于【CryptoZombies - 1 Solidity 教程】013 永久存储变量(storage)和 临时存储变量(memory)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/482040

相关文章

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

python连接本地SQL server详细图文教程

《python连接本地SQLserver详细图文教程》在数据分析领域,经常需要从数据库中获取数据进行分析和处理,下面:本文主要介绍python连接本地SQLserver的相关资料,文中通过代码... 目录一.设置本地账号1.新建用户2.开启双重验证3,开启TCP/IP本地服务二js.python连接实例1.

Python 安装和配置flask, flask_cors的图文教程

《Python安装和配置flask,flask_cors的图文教程》:本文主要介绍Python安装和配置flask,flask_cors的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,... 目录一.python安装:二,配置环境变量,三:检查Python安装和环境变量,四:安装flask和flas

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处