Solidity语法知识点(文末有彩蛋)

最近报名参加了硅谷区块链举办的《智能合约开发课》第二期培训班,根据培训要求,不能透露课程的内容,但我会在steemit上不断地记录我的成长过程。

https://steemit.com/cn/@speeding/smart-contract-development0

单纯地学Solidity的语法知识点非常枯燥,而放在一个个的实际例子中逐步深入时,则轻松了许多,当前已经学完了智能合约开发课的第三课,必须抓紧把学过的语法点总结一下。

一、文件名

solidity文件的扩展名为*.sol

二、指定编译器版本

pragma solidity ^0.4.0;

表示源程序在大于等于0.4.0版本的编译器可以正常工作,在大于等于0.5.0版本中的编译器中无法工作。即:

0.4.0 <= version < 0.5.0

关于pragma的详细文档在这里:http://solidity.readthedocs.io/en/develop/layout-of-source-files.html#version-pragma

而版本号之前的“^”符号的含义,来自于npm中的语法 。

三、数据类型

solidity是静态类型语言,所有变量需要有定义声明。

1)整数

常用的无符号整数类型有uint8, uint16, uint24, ... ,uint256。256个字节的无符号整数uint256可以简写为uint。而有符号的整数则从int8, int16一直到int256。

这些整数经常会用来保存用户的token数量,小心加、减、乘、除运算后的结果溢出,那可是非常惨痛的损失。

uint a = 365;

2)地址

address用来存储以太坊的地址,实际上就是不超过20字节的无符号整数,例如:

address a = 0xdd870fa1b7c4700f2bd7f44238821c26f7392148;

后面的0x开头的一串十六进制数并不是字符串,不需要双引号。而在remix调试程序时,传入的地址参数却需要双引号括起来,新手一开始经常会遇到这个错误。

地址有合约地址和普通的钱包地址两种。

3)结构struct

与C语言非常相似,不用多说。

struct Participator {
    address addr;  
    uint amount;
}

4)数组

Solidity支持定长数组:

uint[5] a;

也支持动态数组:

uint []b;

在动态数组中增加一个元素用push()函数。

b.push(1);

b.push(2);

b.length得到数组的长度,还可以直接修改length来删除元素。

b.length = 1;

5)mapping类型

这种类型相当于其它语言中的哈希表,一开始不太适应,是solidity中非常重要的一种数据类型,以后再展开。

6)var

var并不是表示动态类型,而是让书写更简单,一个值在分配给var变量时,其类型就已经确定了。如果要赋值给其它类型,仍要进行强制类型转换。

7)其它类型

solidity中还支持布尔类型、字符串类型、枚举类型等等。非常神奇,这次的培训课中竟然一直没讲string类型,通常的编程语言都会在第一课介绍"hello world"。可能智能合约是与token打交道,而不是输出字符串吧。

四、函数修饰符

function modifier可以让函数显得更加简洁,比如经常判断一个函数的msg.sender是不是合约构建者时,不需要频繁插入require(msg.sender == owner);这样的语句,只需要定义一个modifier。

modifier onlyOwner {
    require(msg.sender == owner);
    _;
}

而在函数声明的主体尾部加上onlyOwner就可以了。上面的语法中最有意思的是_;这行语句,表示原来函数中的所有语句。当函数中含有return()语句时,替代规则有点特殊。

function test() onlyOwner { 
   // ...
}

payable实际是一个内置的修饰符,表示一个函数在调用时要发送ether。

五、继承

solidity支持多重继承,继承线采用与Python相似的C3 Linearization规则。

contract parent {
    // ...
}
contract child is parent {
    // ...
}

抽象合约是函数只有声明,没有具体的实现。

interface与java语言的语法类似,不用多说。

六、多参数返回

在函数的返回值中可以一次返回多个参数,比如:在返回一个数组中的元素的同时,返回它在数组中所在的位置时,这样可以一次给多个变量赋值。

function test() returns (address item, uint index) {
    address []arr;
    // ...
    return (arr[1], 1);
}
address owner;
uint i;
(owner, i) = test();
(owner, ) = test(); //如果不需要第2个参数

七、异常处理

在比较早的solidity版本中都用throw(),现在统统用revert(),可以保证在遇到异常时,回滚到调用前的状态。用require可以写得更简练。

require(msg.sender == owner);

另外的一个容易让人搞糊涂的语句是assert,在C语言中,assert翻译为“断言”,这类语句只在调试时起作用,用来排查软件的重大BUG,这里也是类似。表示程序在执行到这条语句时,肯定会满足其中的情况。如果有异常发生,说明软件肯定有重大的BUG,由于solidity中涉及到转帐等重要操作,assert失败后,会耗光所有的GAS,让交易失败,防止更严重的事情发生。assert常用于数组越界、元素非空的检查上。

而require要检查的是软件可能经常发生的情况,比如给函数中传递的参数时是否满足一定的条件等等。

八、几个全局变量

solidity中内置了msg,block和tx这几个全局变量。

  • msg.value,消息所附带的货币量,单位为wei
  • msg.sig,调用数据的前四个字节,函数标识符
  • msg.sender,当前调用发起人的地址
  • msg.gas,当前剩余的gas
  • block.difficulty,当前区块的难度值
  • block.blockhash(),某个区块的哈希值
  • block.coinbase,当前区块矿工的地址
  • block.gaslimit,当前区块的gas上限
  • block.number,当前区块的序号
  • block.timestamp,当前区块的时间戳,是uint类型
  • now,等同于block.timestamp
  • tx.gasprice,交易的gas价格
  • tx.origin,交易的发起人,完整的调用链

九、可见性

函数的可见性有external、public、internal和private。

状态变量的可见性有public、internal和private,类似于C++语言中的public、protected和private。

external只能修饰函数,说明这个函数只能被外部合约调用。假设函数f()是external,还想在合约内调用,可以用this.f()。

十、delete

delete操作可以用于任何变量,将其设置为默认值0。

对可变数组使用delete,会删除所有元素,其长度变为0。

对定长数组使用delete,则会重置所有元素为0,也可以重置指定位置的元素。

对map类型使用delete,什么也不会发生。

对map类型的一个键使用delete,则会删除与该键相关的值。

我学习合约编程的目的是什么呢?

1、手工用imtoken钱包给许多人发代币是一件非常费力且容易出错的事,想写一个合约来自动完成这件事。

2、深入了解以太坊的背后原理。

3、智能合约在写作社群激励等很多地方有广阔的应用前景,程序员学会它肯定是站在区块链的顶端,既有趣又赚钱。

原文发布于微信公众号 - 申龙斌的程序人生(slbGTD)

原文发表时间:2018-01-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微信公众号:Java团长

Java经典设计模式之五大创建型模式(附实例和详解)

(1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

801
来自专栏Fundebug

5分钟掌握JavaScript小技巧

1084
来自专栏MyBlog

Effective.Java 读书笔记(8)关于equals方法

重写equals看上去十分简单对吧,但是我觉得很多时候重写equals可能会招致一些问题,这些问题有时可能会特别严重,当然了不重写不就完事了吗?但是这只适用于那...

584
来自专栏C/C++基础

STL四种智能指针

STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr,auto_ptr是C++98提供的解决方案,...

1272
来自专栏HTML5学堂

原生JS | 逻辑操作符的短路问题

HTML5学堂-码匠:短路,并不仅仅存在于物理学当中,JavaScript中的逻辑操作符也有短路问题,这个问题时常作为前端的考点出现哦! 面试真题 var a ...

3485
来自专栏微信公众号:Java团长

Java开发中如何正确踩坑

之前在这个手册刚发布的时候看过一遍,当时感觉真是每个开发者都应该必读的一本手册,期间还写过一篇关于日志规约的文章:《下一个项目为什么要用 SLF4J》,最近由于...

764
来自专栏李成熙heyli

babel到底将代码转换成什么鸟样?

前言 将babel捧作前端一个划时代的工具一定也不为过,它的出现让许多程序员幸福地用上了es6新语法。但你就这么放心地让babel跑在外网?反正我是不放心,我就...

32410
来自专栏C语言C++游戏编程

C语言第一个字符串Hello,C语言基础教程之字符串

C 语言中,字符串实际上是使用 null 字符 '' 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。

832
来自专栏Java面试通关手册

最最最常见的Java面试题总结-第一周

这里会分享一些出现频率极其极其高的面试题,初定周更一篇,什么时候更完什么时候停止。

651
来自专栏Android干货园

Kotlin初级(1)- - - 基础.md

使用package包可以将代码分割到各个命名空间内。所谓命名空间,就好比咱们的国内重名的地区非常多,如果单独将一个地名,很可能引起歧义,但如果按省来划分,就解决...

693

扫码关注云+社区