以太坊智能合约 Solidity 的常用数据类型介绍

2017-11-11 11:42:28来源:https://mshk.top/2017/11/solidity-types/作者:陌生的山不知名的花人点击

分享
目录

Contents




1.1、对数组的增删改查操作。
2、String、Bytes、Mapping的使用
3、Enums 和 Structs 的简单应用
4、Ether 单位和 Time 单位

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] 是从右边剔除了一阶)。


bytes 和 string 是特殊类型的数组。 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 类型有两个成员, length 和 push


更多介绍参考链接: 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 文件,对 string 、 bytes 、 mapping 进行测试。


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) 一样, KeyType 和 ValueType 可以是任何类型,其中 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 中创建以后,能够看到如下图中的效果:



最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台