美文网首页学习永远无止境
孤荷凌寒自学python第111天区块链025eth智能合约00

孤荷凌寒自学python第111天区块链025eth智能合约00

作者: f9e86c58f23c | 来源:发表于2020-03-06 22:54 被阅读0次

    孤荷凌寒自学python第111天区块链025eth智能合约004

    【主要内容】

    今天先继续理解使用Solidity编程语言来发布一个智能合约的基本概念,将昨天理解得不很透彻的地方通过阅读其它博文进行深入理解,学习共用时34分钟。

    (此外整理作笔记花费了约70分钟)

    今天的学习显得非常凌乱,感觉像是在漫无目的的不断看别人的代码案例,不过这种泛学,确实激发了我的灵感,因此发现从别人的代码开始看起的学习方式是比较适合入门的。

    详细学习过程见文末学习过程屏幕录像。

    【学习笔记】

    一、修改整理并理解昨天 Solidity中文版的官方文档中的ETH的基础知识部分的认识

    此文档内容来自:

    http://wiki.jikexueyuan.com/project/solidity-zh/introduction-smart-contracts.html

    今天的感觉是,我看有的博文说5分钟就可以通过eth网络发一个代币,我都花了十多个小时了,还没搞定,这个差距不是一般般的大啊!不过也没有关系,谁叫我是超级小白呢?只要我每天都在学习一点那就是成功的。

    今天找到并准备参考学习的博文:

    1.介绍remix这个在线编辑器简单使用方法为主的博文:

    https://my.oschina.net/u/2275217/blog/1798348

    https://juejin.im/entry/5a9b8e996fb9a028c3684359

    https://ethfans.org/posts/deploying-smart-contract-with-remix

    (上面三篇博文内容基本一样,第一篇还带有收费广告,建议阅读第二篇第三篇)

    https://cloud.tencent.com/developer/article/1182404

    https://www.jianshu.com/p/c3ac1dbdf336 (简单易懂一点)

    2.连代码都不用写,直接发代币的方法,博文是:

    http://wangmengqi.logdown.com/posts/2473648-tutorial-workshop-on-smart-contracts-issued-tokens

    使用的网站工具:

    http://tokenfactory.surge.sh/#/factory

    3.介绍ETH代币规则的博文:

    https://ethfans.org/ajian1984/articles/1007

    对上文的详细补充:

    https://mp.weixin.qq.com/s/foM1QWvsqGTdHxHTmjczsw


    https://www.bcgfans.com/topics/78 (使用手册)

    4.gihub上的范例代码

    https://github.com/ConsenSys/Token-Factory/tree/master/contracts

    5.一步步创建一个智能合约的博文:

    https://www.jianshu.com/p/ce9417905b97 (内容很详细)

    https://www.cnblogs.com/Evsward/p/contract.html (比较细致底层一些,作者讲得很清楚)

    https://it-node.iteye.com/blog/2419957

    https://blog.csdn.net/yinanmo5569/article/details/80372133

    6.solidity语言学习的网站:

    https://cryptozombies.io/zh/ 边玩边学的好网站。

    下面补充在昨天基础上的理解。

    (一)交易/事务(昨天已理解,今天不再作补充理解)

    区块链是一个全局共享的,事务性的数据库。这意味着参与这个网络的每一个人都可以读取其中的记录。如果你想修改这个数据库中的东西,就必须创建一个事务,并得到其他所有人的确认。事务这个词意味着你要做的修改(假如你想同时修改两个值)只能被完完全全的实施或者一点都没有进行。

    此外,当你的事务被应用到这个数据库的时候,其他事务不能修改该数据库。

    举个例子,想象一张表,里面列出了某个电子货币所有账号的余额。当从一个账户到另外一个账户的转账请求发生时,这个数据库的事务特性确保从一个账户中减掉的金额会被加到另一个账户上。如果因为某种原因,往目标账户上增加金额无法进行,那么源账户的金额也不会发生任何变化。

    此外,一个事务会被发送者(创建者)进行密码学签名。这项措施非常直观的为数据库的特定修改增加了访问保护。在电子货币的例子中,一个简单的检查就可以确保只有持有账户密钥的人,才能从该账户向外转账。

    【我的理解】这个知识点非常熟悉,因为之前已经基本了解了它的概念,就是如何在区块链 网络上完成一次交易,在这里呢交易被更准确的描述为:事务。

    这儿的知识增加了广播的实际概念,当一个次交易的发送者广播交易信息时,实际上做的事情是:将交易信息存放到区块链网络的“数据库”中,这个数据库当然不是传统的关系型数据库,而是类似于非关系型的数据库——如mongodb那样的key-value对存储的格式。

    当然在区块链网络中,是不存在这样的中心化数据库的,这只是一种比喻。

    一次交易事务,由发起交易的发送者广播,但必须得到全网节点认可,此次事务才能确认被实施,因为上面一段话已经说了,事务只有两个结果状态——要么是:完全实施的结果状态;要么是:完全没有被实施的结果状态。

    (二)区块(昨天已理解,今天不再作补充理解)

    区块链要解决的一个主要难题,在比特币中被称为“双花攻击”。当网络上出现了两笔交易,都要花光一个账户中的钱时,会发生什么?一个冲突?

    简单的回答是你不需要关心这个问题。这些交易会被排序并打包成“区块”,然后被所有参与的节点执行和分发。如果两笔交易相互冲突,排序靠后的交易会被拒绝并剔除出区块。

    这些区块按时间排成一个线性序列。这也正是“区块链”这个词的由来。区块以一个相当规律的时间间隔加入到链上。对于以太坊,这个间隔大致是17秒。

    作为“顺序选择机制”(通常称为“挖矿”)的一部分,一段区块链可能会时不时被回滚。但这种情况只会发生在整条链的末端。回滚涉及的区块越多,其发生的概率越小。所以你的交易可能会被回滚,甚至会被从区块链中删除。但是你等待的越久,这种情况发生的概率就越小。

    (三)以太坊虚拟机

    1.总览

    以太坊虚拟机(EVM)是以太坊中智能合约的运行环境。它不仅被沙箱封装起来,事实上它被完全隔离,也就是说运行在EVM内部的代码不能接触到网络、文件系统或者其它进程。甚至智能合约与其它智能合约只有有限的接触。

    【今天的理解】EVM,即eth开发合约solidity语言运行所需要的虚拟机,正如java编写的代码运行在JVM一样,在同一个区块链中每一个结点的EVM都是相同的运行环境。通过智能合约,可以开发匿名投票、匿名拍卖、众筹以及多重签名的钱包等,以太坊每一个结点可以有多个账户,所以每个结点都可以称作钱包,可以管理名下的账户,以及转账、挖矿等操作。

    2.账户(昨天已理解,今天不再作补充理解)

    以太坊中有两类账户,它们共用同一个地址空间。外部账户,该类账户被公钥-私钥对控制(人类)。合约账户,该类账户被存储在账户中的代码控制。

    外部账户的地址是由公钥决定的,合约账户的地址是在创建该合约时确定的(这个地址由合约创建者的地址和该地址发出过的交易数量计算得到,地址发出过的交易数量也被称作"nonce")

    合约账户存储了代码,外部账户则没有,除了这点以外,这两类账户对于EVM来说是一样的。

    每个账户有一个key-value形式的持久化存储。其中key和value的长度都是256比特,名字叫做storage.

    另外,每个账户都有一个以太币余额(单位是“Wei"),该账户余额可以通过向它发送带有以太币的交易来改变。

    【我的理解】

    (1.)

    1eth=100亿亿Wei=1000000000000000000Wei=10e18Wei

    (2.)

    多数普通以太坊网络节点的用户的账户地址是属于外部账户,有公钥-私钥对决定。

    而合约账户应当指的是创建合约后合约所在的节点,一般地址是:0?(仍然没有系统理解,这就是半路出家学习的问题)

    3.交易

    一笔交易是一条消息,从一个账户发送到另一个账户(可能是相同的账户或者零账户,见下文)。交易可以包含二进制数据(payload)和以太币。

    如果目标账户包含代码,该代码会执行,payload就是输入数据。

    如果目标账户是零账户(账户地址是0),交易将创建一个新合约。正如上文所讲,这个合约地址不是零地址,而是由合约创建者的地址和该地址发出过的交易数量(被称为nonce)计算得到。创建合约交易的payload被当作EVM字节码执行。执行的输出做为合约代码被永久存储。这意味着,为了创建一个合约,你不需要向合约发送真正的合约代码,而是发送能够返回真正代码的代码。

    【以上文字仍然完全没有理解 】

    【新补充学习到的内容】

    根据多篇博客文章提到的观点,创建智能合约(今天阅读的多篇博文都是讲如何创建一个可以发布自己新的代币的智能合约的,与之前研究的以完成具体解决方案的智能合约不同),创建智能合约所使用的那个eth地址就是智能合约的拥有地址,如果是发新代币的智能合约,则可以直接指定预发多少代币给这个eth地址(这一点令我非常兴奋啊)。

    而上面一段没有完全理解的文字内容,估计讲解的是具体如何通过代码来实现代币交易,因为实在很含糊,跳过不再去深入理解。

    【此笔记的第二天返回来补充的笔记】

    当合约被一个eth节点的地址第一次部署(创建create)时,在eth网络中查看到的记录是:

    from 合约创建者的eth节点地址 to 创建(部署)成功的新合约所在的地址。

    4.Gas

    以太坊上的每笔交易都会被收取一定数量的gas,gas的目的是限制执行交易所需的工作量,同时为执行支付费用。当EVM执行交易时,gas将按照特定规则被逐渐消耗。

    gas price(以太币计)是由交易创建者设置的,发送账户需要预付的交易费用 = gas price * gas amount。 如果执行结束还有gas剩余,这些gas将被返还给发送账户。

    无论执行到什么位置,一旦gas被耗尽(比如降为负值),将会触发一个out-of-gas异常。当前调用帧所做的所有状态修改都将被回滚。

    【我的理解】这就是在以太坊网络上进行所有交易往来时,都要支付的“油费”

    【今天新的理解】在eth网络上进行的智能合约,不管执行什么操作,无论是交易还是转账还是别的什么具体的区块链项目内容,都是需要在每次进行交易(把前面的操作都视为交易)时,给eth网络支付eth代币(这个数量不会很多),这个额外支付的费用就是Gas(一般称之为:油费)

    gas的计算方式是

    gas 单价 × gas 数量

    其中gas单价是由用户,像我们这样的发起者愿意为此次操作付出多少以太币而定的(相当于你开车上路前愿意给你的油箱加多少油,假设你的油箱是无限大的)。gas数量是程序根据你操作的复杂度自动定义的。

    智能合约也是一样的,当一个发起者部署运行一段智能合约时,以太坊会收取gas费用,就像汽车行驶需要烧油一样,直到你的智能合约运行完毕,“油箱”中剩余的gas会退还给你,如果你的代码死循环了,耗尽了你“油箱”中的gas,那么以太坊会自动报出异常停止你的智能合约。

    (昨天笔记中的5-11要点,由于今天学习时间有限,仍然没有任何学习进展,于是省去此部分笔记内容。)

    二、了解到标准的发行自己代币的erc-20标准eth智能合约协议

    经过今天的学习,发现之前研究的智能合约代码并没有遵守erc-20的标准协议,因为里面要求必须的接口部分都没有,因此得出初步结论,只有要发行自己代币的智能合约才需要严格执行erc-20标准。而一些要解决某些需求而开发的智能合约,如果只是使用eth作为代币则完全可以无视这些标准接口。而之前一直学习的那个范例合约代码并没有要发行自己的代币,因此还没有使用到erc-20标准。

    整理的笔记如下:

    ERC20的标准接口是这样的:

    contract ERC20 {

    function name() constant returns (string name)

    function symbol() constant returns (string symbol)

    function decimals() constant returns (uint8 decimals)

    function totalSupply() constant returns (uint totalSupply);

    function balanceOf(address _owner) constant returns (uint balance);

    function transfer(address _to, uint _value) returns (bool success);

    function transferFrom(address _from, address _to, uint _value) returns (bool success);

    function approve(address _spender, uint _value) returns (bool success);

    function allowance(address _owner, address _spender) constant returns (uint remaining);

    event Transfer(address indexed _from, address indexed _to, uint _value);

    event Approval(address indexed _owner, address indexed _spender, uint _value);

    }

    1.

    name

    返回ERC20代币的名字,例如"My test token"。

    symbol

    返回代币的简称,例如:MTT,这个也是我们一般在代币交易所看到的名字。

    decimals

    返回token使用的小数点后几位。比如如果设置为3,就是支持0.001表示。

    totalSupply

    返回token的总供应量

    balanceOf

    返回某个地址(账户)的账户余额

    transfer

    从代币合约的调用者地址上转移 _value的数量token到的地址 _to,并且必须触发Transfer事件。

    transferFrom

    从地址 _from发送数量为 _value的token到地址 _to,必须触发Transfer事件。

    transferFrom方法用于允许合同代理某人转移token。条件是from账户必须经过了approve。这个后面会举例说明。

    approve

    允许 _spender多次取回您的帐户,最高达 _value金额。 如果再次调用此函数,它将以 _value覆盖当前的余量。

    allowance

    返回 _spender仍然被允许从 _owner提取的金额。

    由于时间关系,对此部分的理解还不够深刻,也没有完全去研读代码实现:

    初步理解如下:

    (重点阅读博文:https://mp.weixin.qq.com/s/foM1QWvsqGTdHxHTmjczsw

    (1)这儿一般有三个对象:

    A:需要使用区块链上某项服务(称之为服务合约)的一个用户节点——称之为需求发起者sender.

    B:此用户节点A所依托的代币智能合约(我的理解是就是一些由代码组成的执行某些特定代币发行,交易等操作的源代码,以完成智能合约需要的操作)

    C:提供一定服务的服务合约(我的理解是,这个合约执行的是具体的服务功能,如提供存储信息服务这样的具体功能)

    (2)A想要使用C的服务,基本操作过程如下:

    1)A授权C可以动用自己节点地址所对应的代币账户中的指定金额的代币,并告诉B自己已经授权C这么做了。

    这个过程我今天简单理解,就是通过调用B的approve函数方法来授权的。

    2)A发起一次交易需求,要使用C的一项服务,把需求具体数据发送给 C.

    这是A通过调用B中的storeData()函数方法来实现的。就是告诉C我要使用你的服务,请你执行你的合约协议。

    3)C收到请求后,直接将A节点账户中的指定需要的代币转移给自己,以购买C的服务,因为A在第1)步已经授权C么做了(当然C只能运用A授权部分金额的代币,因此allowance事件将返回C是否还有多少代币金额的授权权限。)

    C要完成这一部分操作是调用B中的transferFrom() 函数方法来实现的。

    4)C最后执行A需要的服务(将先解析A传送过来的数据,然后根据自己的服务合约的代码来完成指定操作),完成本次服务交易。

    而之前研究的那个智能合约代码没有涉及到要发行新的代币,也就是没有出现上面的对象B,因此之前的那个智能合约也就没有遵照ERC-20标准协议,只需要实现直接使用eth作为代币来完成指定的服务需求即可。

    最开始的时候,作为初学者,我发现不同的针对以太坊开发的智能合约竟然没有统一的架构的样子,今天才完全明白,有是否遵守ERC-20协议的区别,如果是一个要发行新的代币的智能合约,就必须遵守erc-20协议,如果不需要发行新的代币,则可以不遵守这个协议。

    同时ERC-20协议也并不是以太坊智能合约开发协议的终极版本,其实已经有了不少的升级版本。

    三、对solidity语言的进一步学习了解

    参见博文:https://www.cnblogs.com/Evsward/p/contract.html

    (一)今天终于了解到Solidity比较正式的说明:

    Solidity是静态类型语言,跟java一样,也就是说在编译之前都要指定好每个变量的具体类型。类型可以分为值类型和引用类型,与java类似。

    (二)Solidity语言的数据类型

    1.值类型

    值类型作为参数时永远传的是值,每一次入参出参都是内存中值的副本。

    包括:

    (1)布尔类型bool

    true\false

    (2)整型int

    与go语言相同,有符无符int/uint,从长度8到256(int8, int16, int32... int256),

    数学运算也包括位运算。

    (3)定长浮点型fixed

    有符无符fixed/ufixed

    据说还未完全被Solidity支持,似乎只可声明还不能赋值,那这就很奇怪了,怎么用?

    (4)定长字节数组(byte/bytes1, bytes2, bytes3, ..., bytes32)

    有个length属性可以取出长度。

    (5)变长字节数组(bytes, string)

    与以上定长类型不同的是,变长类型不必预先指定长度,但bytes和string都属于引用类型,分为以下类别:

    1)地址类型address

    根据以太坊结点、账户、合约等address的概念设计,长度限制为20字节。

    address封装好了一个balance属性,可以代入节点地址就可查看此节点对应账户的代币余额,以及transfer方法(事件?),可以直接转账,非常方便。此外它还有send、call等很多常用方法,这是Solidity封装好的一个基本类型,这就非常适用于智能合约开发。

    2)枚举类型enum

    例如“enum ColorEnums {Red, White, Black}”,注意返回的都是下标值,Red会返回0,White返回1,Black返回2。

    3)函数类function

    变量可以作为其他function的参数,也可以作为其他function的返回值。

    方法在参数后面可以声明函数可见性,

    分为:

    public(任意合约)

    private(当前合约)

    internal(当前合约以及继承合约)

    external(仅外部访问)

    external是由address和function签名组成,可作为外部调用函数的参数或者返回值,默认情况无显式声明时就是internal。

    function还需要声明返回值类型,returns (type),但若方法无返回值时要省略这个部分。

    另外还有特殊的部分是在internal和returns中间还可以加入一个配置属性,[pure|constant|view|payable]。

    constant标识了一个常量不会被更改,只读不可写入。

    view是查看区块链上的数据的意思,比constant更加准确地表达了只是看看,不做修改的意图 。

    pure是纯函数的意思,就是保证不读取和写入到区块链内存的函数。

    payable是声明了该函数设计支付操作,需要虚拟机提供事务支持。


    下面是针对以上类型的字面量类型:

    字面量是一种针对某种值的表示法,简单来说,就是变量赋值时必须是等号右边的部分。

    1)Address字面量,十六进制字面量的一种特殊情况:长度在为40个十六进制数(一个字节8位可存储两个十六进制数,一个4位),且通过了address checksum 校验。

    2)有理数整型字面量,整数,小数,科学计数法2e10,最广泛的字面量类型。

    3)字符串字面量,单引号、双引号均可的字符串。

    4)十六进制字面量,hex开头,例如hex"001122FF",必须是一个字符串,内容必须是十六进制。

    2.引用类型

    1)数据位置类型

    包括:

    memory(内存-临时)

    storage(区块链-永久)

    通过在变量名前声明memory还是storage来定义该变量的数据位置。

    一般来讲,函数参数默认为memory

    局部复杂类型(作用域为局部)以及状态变量(作用域为全局)属于storage类型。

    还有一个calldata与memory差不多,专门用于存储函数参数的,也不是永久存储。(是什么呢?资料上居然没有讲!!)

    EVM的memory是基于stack的,stack可以临时存储一些小的局部变量。这些变量存储消耗的gas是不同的,storage最大,memory较小,stack几乎免费,calldata与memory差不多。

    2)数组类型Arrays

    长度可定可变,可以存储于storage和memory,元素类型可以是任何类型,但memory时不能是映射类型(就是键值对类型)。

    3)结构体struct

    与Go语言相同的设定,自定义类型,使用方式也与Go极为相似。(其实我对Go语言也是一无所知啊!)

    经过阅读具体的结构体代码如:

    struct position{

    int lat;

    int lng;

    }

    结果发现其它主流编程语言中,都有这种结构体,其实就是自定义的组合数据类型,这种组合结构体数据类型中,可以包含已知的其它数据类型。

    4)mapping类型

    mapping类型就是键值对,现在最新语言都会给自身增加键值对数据结构的封装支持。mapping的声明方式为:

    mapping(_KeyType => _ValueType)

    键值对中间通过一个“=>”连接。元素内容,Solidity类型均可,与其他键值对使用差不多。

    (三)Solidity自身携带的特殊变量以及函数

    其实部分内置变量与函数已经在之前的范例代码中研究过了。

    block.blockhash(uint blockNumber) returns (bytes32)

    返回参数区块编号的hash值。(范围仅限于最近256块,还不包含当前块)

    block.coinbase (address)

    当前区块矿工节点地址

    block.difficulty (uint)

    当前区块难度(没有理解。)

    block.gaslimit (uint)

    当前区块的gaslimit(没有理解)

    block.number (uint)

    当前区块编号

    block.timestamp (uint)

    当前区块的timestamp,使用UNIX时间秒

    msg.data (bytes)

    完整的calldata(应当是发起需求的节点(发送方)发送的数据)

    msg.gas (uint)

    剩余的gas(前面了解过的油费)

    msg.sender (address)

    信息的发送方 (当前调用这个智能合约的节点地址)

    msg.sig (bytes4)

    calldata的前四个字节 (i.e. 函数标识符)

    msg.value (uint)

    消息发送的wei的数量(没有完全理解)

    now (uint)

    当前区块的timestamp (block.timestamp别名)

    tx.gasprice (uint)

    交易的gas单价

    tx.origin (address)

    交易发送方地址(完全的链调用)(这个也没有完全理解)

    msg有两个属性,一个是

    msg.sender

    另一个是

    msg.value

    这两个值可以被任何external函数调用,包含库里面的函数。


    注意谨慎使用block.timestamp, now and block.blockhash,因为他们都是有可能被篡改过的。

    【学习后记】

    因为突然发现网络上不同范例的智能合约竟然有完全不同的代码架构,感觉非常无所适从,就尝试去寻找出共同点,找了大量的博文来准备阅读,由于学习时间的关系,其实没有读完多少,理解的东西就更少了。最终来看结果,今天算是学习走偏路了,我其实应当继续把之前的阅读批注的第一个范例进行实际测试的。

    当然今天的学习还是很有收获的,我发现这个eth的智能合约的应用是如此广泛,虽然不能说可以“包治百病”,却真的是异彩纷呈,已经是一个庞大的规模了。 此外也了解了,依托一eth来发行一个自己的代币,并完成一个区块链项目还真的比较方便,这也就是区块链领域可以一下子出现那么多代币项目的原因,ETH已经真正把自己变成了一个生态系统的平台,这就是区块链2.0的代表,后面出现的eos,trx之类的区块链网络也大致如此。当然今天的区块链已经发展到以跨链为特征的区块链3.0了。

    这也许正应了kk所说的,科技自己都会进化发展,根本无需人类操心它的方向,说不定我们人类自始至终都不过是科技这只怪兽所使用的部分工具而已。

    【关于坚持自学的例行说明】

    最后例行说明下,我为什么要坚持自学。

    “如果我不曾见过太阳,我本可以忍受黑暗,然而阳光已使我的荒凉,成为更新的荒凉。”

    ——艾米莉·狄金森

    如果要问我对自己的前半生如何看待时,我想昨天和今天的答案都将完全不同。

    昨天的我,生活在荒凉的满意之中,自觉怡然自得,拿着包身包月的工资,听着仁慈的命令,过着几乎一成不变的生活;时而与周遭的人儿和睦互往,时而唇舌相抵斤斤计较,演出着生活的鸡毛蒜皮,工作的吹拉弹唱;忘我,忘我,才能融入这平和无奇的乐章中,迈着细碎的步伐,原地踏步。那时的我觉得这就是悠然自得的听天由命的平凡人生,也就是我的宿命了。

    可是某一天,我见到了不一样的太阳以及太阳下不一样的人生光景——那并不荒凉。

    今天的我,生活在荒凉的痛苦之中,自觉渴望改变,迈着不知所措的步伐,看着流逝的年华,睁着悔恨错失一切的双眼… …

    我知道我将再无法回到过去的我,只有改变才是唯一正确的方向。

    一、为什么一把年纪还在学习

    放弃很多去聚餐,去HI歌,去游玩,去看电影,去追剧……的时间,然后进行着这个年纪似乎已不应当再进行的学习,引来身边人们无尽的不解与鄙夷甚至可怜……

    但我不想放弃终身学习的誓言。

    因为——

    我对我今天的生活现状并不认同!

    罗伯特清崎告诉过我们,反省自己当下的生活是不是自己想要的,这难道不是最好的动力与答案?

    走过了大半生,然后才发现曾经、当下所正在进行的人生并不是自己想要的,那是一种怎样的体验?

    只有心中真切的感受才能回答这个问题,而任凭再丰富的语言也是无法描绘出来的。

    经历半生的跋涉,却发现走得并不正确,有多少人有勇气承认自己过去的一切都是错误的呢?

    而我愿意告诉过去的我:“你错了!”

    那么已经历半生错误,年岁之大又压于头顶,还有希望从这架的梯子的半端重新爬下,再蹒跚着爬上另一架梯子吗?

    我宁愿相信还有希望!

    这便是我为什么要继续坚持终身学习下去的全部理由。

    二、这个年纪还在学这些技术有意义吗

    纯的技术对这把年纪其实已没有意义。

    但兴趣可以超越意义。

    但技术可以引来思想的变革,这才是意义。

    投资自己的头脑 ,改革自己的思想,这是最保值,更长远的投资,过去我从来没有投资过,错过太多,那就从投资自己头脑开始吧。

    罗伯特清崎告诉我们,真正的富有是时间的富有;真正的自由是可以决定自己愿意做什么的自由。

    因为我愿意做我兴趣所在的事,所以我希望我有自由选择的那一天,虽然今天离那一天可能还是那么遥远,但我愿意相信,每天多赶几步,离希望就更近一步。

    再者,虽然我可能再已无法完全完整的掌握这些技术了,但技术本身却可以启迪心的觉醒,激发灵感,那么只要多了解一点,我相信我将离那个正离我而去跑得越来越快的未来更近一点,不至于被未知的那个未来抛弃得太远。

    于是我怎能放弃追逐求索的步伐?

    我要坚信:感觉太迟的时候,也许还不算太迟。

    感谢一直以来关注我,鼓励我的你!

    若不嫌弃这一个到了高龄才长大的可笑可叹的我,请不吝赐教。

    【同步语音笔记】

    https://www.ximalaya.com/keji/19103006/264191290

    【学习过程屏幕录屏】

    https://www.bilibili.com/video/av93953843/

    相关文章

      网友评论

        本文标题:孤荷凌寒自学python第111天区块链025eth智能合约00

        本文链接:https://www.haomeiwen.com/subject/abiarhtx.html