目录

  Solidity 是一种静态语言类型,在编译前都要指定每个变量的类型。Solidity 提供了几种基本类型,通过几种基本类型的组合,可以组合成复杂类型。

  网络上有很多翻译后的关于 Solidity 类型介绍的文章,这里就不多介绍,只是着重介绍后面实例中会使用到的一些类型。

  上一章节中,我们讲了 使用 Browser-solidity 在 Go-Ethereum1.7.2 上进行简单的智能合约部署,本文中后面的实例,都可以在 Browser-solidity 中进行测试。

  

1、数组

  数组是可以在编译时固定大小的,也可以是动态的。对于存储器数组来说,成员类型可以是任意的(也可以是其他数组,映射或结构)。对于内存数组来说 ,成员类型不能是一个映射;如果是公开可见的函数参数,成员类型是必须是ABI类型的。

  固定大小k的数组和基本类型 T,可以写成 T[k], 动态数组写成 T[ ] 。例如, 有5个基本类型为 uint 的动态数组的数组 可以写成 uint[ ][5] ( 注意,和一些其他语言相比,这里的符号表示次序是反过来的)。为了访问第三动态数组中的第二个 uint, 必须使用 x[2][1](下标是从零开始的,访问模式和声明模式正好相反, 即x[2]是从右边剔除了一阶)。

  bytesstring 是特殊类型的数组。 bytes 类似于 byte[ ],但它是紧凑排列在calldata里的。string 等于 bytes , 但不允许用长度或所以索引访问(现在情况是这样的)。

  所以 bytes 应该优先于 byte[ ],因为它效率更高。

  

1.1、对数组的增删改查操作。

  在Browser-solidity的左侧,新建一个mshk_top_array.sol文件,内容如下:

  mshk_top_array.sol:

pragma solidity ^0.4.17;

/**
* 数组的增、删、改、查
* https://mshk.top
*/
contract mshk_top_array { //声明一个全局数组变量
uint[] public intArray; /*
* 构造函数
* 默认向数组中添加一个2009
*/
function mshk_top_array() public{
intArray.push(2009);
} /*
* @dev 添加一个值到数组
* @param val uint, 要传入的数值
*/
function add(uint val) public{
intArray.push(val);
} /*
* @dev 获取数组的长度
* @return len uint,返回数组的长度
*/
function length() public view returns (uint) {
return intArray.length;
} /*
* @dev 更新数组的值
* @param _index uint, 指定的索引
* @param _value uint, 要修改的值
*/
function update(uint _index, uint _value) public{
intArray[_index] = _value;
} /*
* @dev 获取指定数组索引的值
* @param _index uint, 索引值
* @return _value uint, 返回结果
*/
function valueByIndex(uint _index) public view returns (uint _value){
uint result = intArray[_index];
return result;
} /*
* @dev 删除指定数组索引的值
* @param _index uint, 索引值
*/
function delByIndex(uint _index) public{
uint len=intArray.length;
if (_index >= len) return;
for (uint i = _index; i<len-1; i++){
intArray[i] = intArray[i+1];
}
delete intArray[len-1];
intArray.length--;
}
}

Array类型有两个成员,lengthpush

更多介绍参考链接: http://solidity.readthedocs.io/en/latest/types.html?highlight=uint#members

  

  在左侧写完代码以后,可以在右侧的Setting选择0.4.17+commit.bdeb9e52,然后在Run选项卡中,进行调试。

  之前的文章中有介绍如何使用Browser-solidity调试Solidity,本文中不多介绍,没看过的同学,可以参考 这里

2、String、Bytes、Mapping的使用

  string类型没有length属性,而bytes类型有length属性

  

  bytes1, bytes2, bytes3, ..., bytes32,如果在bytes后面带了数字进行声明时,最多可以保存32个字符。一旦声明以后,那么length属性就是你声明的长度。

  

  mapping,是由键和值组成的mapping(_KeyType => _ValueType)哈希表,初始化每个存在的key,对应的value的值会初始化为所有的字节都为0。_KeyType_ValueType可以是任意类型。mapping只允许静态变量或是内部方法中的存储空间引用类型。一般键为地址, 值为余额 mapping(address => uint)

string类型的官方介绍:http://solidity.readthedocs.io/en/latest/types.html?highlight=uint#string-literals

bytes数组的官方介绍:http://solidity.readthedocs.io/en/latest/types.html?highlight=bytes#fixed-size-byte-arrays

Mappings类型的官方介绍:http://solidity.readthedocs.io/en/latest/types.html?highlight=bytes#mappings

  

  下面我们创建一个mshk_top_string_bytes_mapping.sol文件,对stringbytesmapping进行测试。

  mshk_top_string_bytes_mapping.sol:

pragma solidity ^0.4.17;

/**
* 对`string`、`bytes`、`mapping`进行测试
* https://mshk.top
*/
contract mshk_top_string_bytes_mapping { //声明一个变量
string public str;
bytes public byt;
mapping(bytes10 => string) public map; /*
* 初始化
*/
function init() public{
str = "abc";
byt = "abc";
map["mshk"] = "mshk.top";
map["idoall"] = "idoall.org";
} /*
* @dev 获取长度
* @param uint 返回长度
*/
function lenght() public view returns(uint){
return byt.length;
} /*
* @dev 获取map的指定key的值
* @param _key bytes10,指定的key,如果key不存在,会返回空字符串
*/
function getMapByKey(bytes10 _key) public view returns(string){
return map[_key];
}
}

  

  下图是在Browser-solidity中运行起来的效果:

  

3、Enums 和 Structs 的简单应用

  Enums是一个用户可以定义类型的方法,可以使用uint转换,默认从0开始递增,但不可以隐性转换,转换失败会抛出异常,声明Enums时,里面至少要有一个成员。一般用来模拟合约的状态。

  下面我们创建一个mshk_top_enums.sol文件,对enums进行测试。

  mshk_top_enums.sol:

pragma solidity ^0.4.17;

/**
* 对`enums`进行测试
* https://mshk.top
*/
contract mshk_top_enums { //定义枚举
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } //声明变量
ActionChoices choice;
ActionChoices constant defaultChoice = ActionChoices.GoStraight; function setGoRight() public {
choice = ActionChoices.GoRight;
} function setGoLeft() public {
choice = ActionChoices.GoLeft;
} function setGoStraight() public {
choice = ActionChoices.GoStraight;
} function setSitStill() public {
choice = ActionChoices.SitStill;
} // Since enum types are not part of the ABI, the signature of "getChoice"
// will automatically be changed to "getChoice() returns (uint8)"
// for all matters external to Solidity. The integer type used is just
// large enough to hold all enum values, i.e. if you have more values,
// `uint16` will be used and so on.
function getChoice() public view returns (ActionChoices) {
return choice;
} function getDefaultChoice() public pure returns (uint) {
return uint(defaultChoice);
}
}

  

  以上代码,第一次调用getChoice方法时,返回的值为0。调用setGoRight方法,对choice设置一个枚举值ActionChoices.GoRight,再次调用getChoice方法时,返回的值为1.

  下图是在Browser-solidity中运行起来的效果:

  

  Structs结构体,和其他语言一样,可以定义任意类型的结构。Structs里面可以定义Mappings,同样在Mappings中也可以定义Structs。虽然结构本身可以作为mapping的成员值,但是结构不可以包含它本身类型,避免死循环。

  下面我们创建一个mshk_top_struct.sol文件,对structs进行测试。

  mshk_top_struct.sol:

pragma solidity ^0.4.17;

/**
* 对 structs 进行测试
* https://mshk.top
*/
contract mshk_top_struct { // Defines a new type with two fields.
struct User {
string name;
uint age;
} //用户列表
User[] public users; /*
* @dev 添加方法
*/
function add(string _name, uint _age) public{
users.push(
User({
name:_name,
age:_age
})
);
}
}

  以上代码,在add方法中,输入"张三",18,然后在users中输入索引值0,能够看到如下图中的效果:

  

  Mapping类型被定义成如mapping(_KeyType => _ValueType)一样,KeyTypeValueType 可以是任何类型,其中 ValueType 甚至也可以是Mapping类型。

  mshk_top_struct_mapping.sol:

pragma solidity ^0.4.17;

/**
* 使用 struct 和 mapping 编写一个简单的智能合约
* https://mshk.top
*/
contract mshk_top_struct_mapping { mapping (address => uint) public balanceOf;
address public owner;
event Sent(address sender, address receiver, uint amount); //定义一个时间 //获取部署合约的账户地址, 并初始化该地址的余额
function mshk_top_struct_mapping() public{
owner = msg.sender;
balanceOf[owner] = 10000;
}
//账户地址交易
function transfer(address _to, uint amount) public{
if(balanceOf[msg.sender] < amount) {return;} //进行判断,防止发送账户的余额不足
if(balanceOf[_to] + amount < balanceOf[_to]){return;} //防止自己给自己转账,或递归调用(因为每次调用都有额外的花费)
balanceOf[_to] += amount;
balanceOf[msg.sender] -= amount;
Sent(msg.sender, _to, amount); ///调用事件
} //挖矿
function mint(uint amount) public{
balanceOf[owner] += amount;
} }

  以上代码,在Browser-solidity中创建以后,能够看到如下图中的效果:

  

4、Ether 单位和 Time 单位

  Ether的单位关键字有wei, finney, szabo, ether,换算格式如下:

  • 1 ether = 1 * 10^18 wei;
  • 1 ether = 1 * 10^6 szabo;
  • 1 ehter = 1* 10^3 finney;

  mshk_top_ether.sol:

pragma solidity ^0.4.17;

/**
* 对 比特币 Ether 的几个单位进行测试
* https://mshk.top
*/
contract mshk_top_ether { // 定义全局变量
uint public balance; function mshk_top_ether() public{
balance = 1 ether; //1000000000000000000
} function mshk_finney() public{
balance = 1 finney; //1000000000000000
} function mshk_szabo() public{
balance = 1 szabo; //1000000000000
} function mshk_wei() public{
balance = 1 wei; //1
}
}

  以上代码,在Browser-solidity中创建以后,能够看到如下图中的效果:

  

  Time的单位关键字有seconds, minutes, hours, days, weeks, years,换算格式如下:

  • 1 == 1 seconds
  • 1 minutes == 60 seconds
  • 1 hours == 60 minutes
  • 1 days == 24 hours
  • 1 weeks == 7 days
  • 1 years == 365 days

  mshk_top_time.sol:

pragma solidity ^0.4.17;

/**
* 对 Time 单位进行测试
* https://mshk.top
*/
contract mshk_top_time { // 定义全局变量
uint public _time; function mshk_top_time() public{
_time = 100000000;
} function mshk_seconds() public view returns(uint){
return _time + 1 seconds; //100000001
} function mshk_minutes() public view returns(uint){
return _time + 1 minutes; //100000060
} function mshk_hours() public view returns(uint){
return _time + 1 hours; //100003600
} function mshk_weeks() public view returns(uint){
return _time + 1 weeks; //100604800
} function mshk_years() public view returns(uint){
return _time + 1 years; //131536000
}
}

  以上代码,在Browser-solidity中创建以后,能够看到如下图中的效果:

  

5、Address

  address类型是一个由 20 字节长度的值(以太坊的地址)组成的。地址类型有很多成员变量,是所有合约的基础。常用的两个成员为:

  • <address>.balance,地址的余额(单位为:wei)
  • <address>.transfer,发送以太币(单位为:wei)到一个地址,如果失败会抛出异常,会撤回发送。

  mshk_top_address.sol:

pragma solidity ^0.4.17;

/**
* 对 Address 的测试
* https://mshk.top
*/
contract mshk_top_address { // 定义全局变量
address public _a;
address public _b; function mshk_top_address() public{
_a = msg.sender; //调用合约用户的地址
_b = this; //当前合约的地址
} function geta() public view returns(address){
return _a;
} function getb() public view returns(address){
return _b;
}
}

  以上代码,在Browser-solidity中创建以后,能够看到如下图中的效果:

6、更多数据类型介绍

  有兴趣的同学,如果想看更多的数据类型介绍 ,可以参考 以太坊数据类型官方文档

7、相关文章

Tools and Technologies in the Ethereum Ecosystem

Solidity撰寫智能合約與注意事項(一)

Types


博文作者:迦壹

博客地址:以太坊智能合约 Solidity 的常用数据类型介绍

转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作!


以太坊智能合约 Solidity 的常用数据类型介绍的更多相关文章

  1. 以太坊智能合约介绍,Solidity介绍

    以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...

  2. Go语言打造以太坊智能合约测试框架(level1)

    传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...

  3. 如何通过以太坊智能合约来进行众筹(ICO)

    前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...

  4. 深入以太坊智能合约 ABI

    开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...

  5. Go语言打造以太坊智能合约测试框架(level3)

    传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...

  6. rpc接口调用以太坊智能合约

    rpc接口调用以太坊智能合约 传送门: 柏链项目学院   在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...

  7. 使用web3.js监听以太坊智能合约event

    传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event   当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...

  8. 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明

    以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...

  9. 以太坊智能合约Hello World示例程序

    简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...

随机推荐

  1. Java引入的一些新特性

    Java引入的一些新特性 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程, ...

  2. Android studio使用过程中错误的解决方法

    错误一:No such property: POM_DESCRIPTION for class: org.gradle.api.publication.maven.internal.pom 刚开始出现 ...

  3. vue组件的基本使用,以及组件之间的基本传值方式

    组件(页面上的每一个部分都是组件) 1.三部分:结构(template),样式(style),逻辑(script) 2.组件的作用:复用 3.模块包含组件 4.组件创建:     1.全局组件:Vue ...

  4. MySQL将utf8字符集改为utf8mb4

    前言 今天在查看tomcat日志时发现了一个错误:Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x82\xF0 ...

  5. Pycharm使用教程(三)(非常详细,非常实用)

    1. 汉化:把resources_zh.jar拷贝到PyCharm的安装目录下的lib目录,重启Pycharm即可. (resources_zh.jar汉化包关注本账号获取:链接: https://p ...

  6. 智能压缩,摆脱用 Gzip 还是 Brotli 的纠结

    近日,又拍云上线了“智能压缩”功能,同时支持 Gzip 和 Brotli 压缩算法,在节约流量的同时,进一步减少用户的等待时间. CDN 流量问题一直以来是大家关注的重点,又拍云针对流量节约上线了一系 ...

  7. Session知识点

    知识点概要    - Session    - CSRF    - Model操作    - Form验证(ModelForm)    - 中间件    - 缓存    - 信号 内容详细: 1. S ...

  8. C#2.0 委托

    委托 委托是一个非常不错的设计,允许我们把方法做为参数传递,实现了开放閉放原则.在方法中我们只要有一个委托占位,调用者就可以传入符合签名的方法来做不同的操作,这也面向对象开发中多态的魅力. 但是在C# ...

  9. ELK-logstash案例实战之读取日志输出到elasticsearch

    简介:从日志文件中读取日志,输出到elasticsearch集群中 $ cd /home/es/logstash-/config $ vim test3_es.conf $ cd /home/es/l ...

  10. kubernetes系列03—kubeadm安装部署K8S集群

    本文收录在容器技术学习系列文章总目录 1.kubernetes安装介绍 1.1 K8S架构图 1.2 K8S搭建安装示意图 1.3 安装kubernetes方法 1.3.1 方法1:使用kubeadm ...