0%

solidity基础7-9

Solidity极简入门: 7. 映射类型 mapping

映射Mapping

在映射中,人们可以通过键(Key)来查询对应的值(Value),比如:通过一个人的id来查询他的钱包地址。

声明映射的格式为mapping(_KeyType => _ValueType),其中_KeyType_ValueType分别是KeyValue的变量类型。例子:

1
2
mapping(uint => address) public idToAddress; // id映射到地址
mapping(address => address) public swapPair; // 币对的映射,地址到地址

映射的规则

==这里的几个规则是重点==

  • 规则1:映射的_KeyType只能选择solidity默认的类型,比如uintaddress等,不能用自定义的结构体。而_ValueType可以使用自定义的类型。下面这个例子会报错,因为_KeyType使用了我们自定义的结构体:
  • ==key只能用默认的,但是value自定义的都可以==
1
2
3
4
5
6
// 我们定义一个结构体 Struct
struct Student{
uint256 id;
uint256 score;
}
mapping(Student => uint) public testVar;
  • 规则2:==映射的存储位置必须是storage==,因此可以用于合约的状态变量,函数中的storage变量,和library函数的参数(见例子)。不能用于public函数的参数或返回结果中,因为mapping记录的是一种关系 (key - value pair)。
  • 规则3:如果映射声明为public,那么solidity会自动给你创建一个==getter函数==,可以通过Key来查询对应的Value
  • 规则4:给映射新增的键值对的语法为_Var[_Key] = _Value,其中_Var是映射变量名,_Key_Value对应新增的键值对。例子:
1
2
3
function writeMap (uint _Key, address _Value) public{
idToAddress[_Key] = _Value;
}

映射的原理

  • 原理1: 映射不储存任何键(Key)的资讯,也没有length的资讯。
  • 原理2: 映射使用keccak256(key)当成offset存取value。
  • 原理3: 因为Ethereum会定义所有未使用的空间为0,所以未赋值(Value)的键(Key)初始值都是各个type的默认值,如uint的默认值是0。

在Remix上验证 (以 Mapping.sol为例)

  • 映射示例 1 部署

    7-1

  • 映射示例 2 初始值

    7-2

  • 映射示例 3 key-value pair

    7-3

总结

这一讲,我们介绍了solidity中哈希表——映射(Mapping)的用法。至此,我们已经学习了所有常用变量种类,之后我们会学习控制流if-else, while等。

Solidity极简入门: 8. 变量初始值

变量初始值

solidity中,声明但没赋值的变量都有它的初始值或默认值。这一讲,我们将介绍常用变量的初始值。

值类型初始值

  • boolean: false

  • string: ""

  • int: 0

  • uint: 0

  • enum: 枚举中的第一个元素

  • address: 0x0000000000000000000000000000000000000000 (或 address(0))

  • function
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    - `internal`: 空白方程
    - `external`: 空白方程

    可以用`public`变量的`getter`函数验证上面写的初始值是否正确:

    ```solidity
    bool public _bool; // false
    string public _string; // ""
    int public _int; // 0
    uint public _uint; // 0
    address public _address; // 0x0000000000000000000000000000000000000000

    enum ActionSet { Buy, Hold, Sell}
    ActionSet public _enum; // 第1个内容Buy的索引0

    function fi() internal{} // internal空白方程
    function fe() external{} // external空白方程

==注意bytes1 初始值是0x00==

==在Solidity中,bytes1 是一种固定长度的字节数组,只能包含一个字节(8位)。它可以用来存储任何8位的数据,包括整数、字符、字节等。但要注意的是,bytes1 中的数据并不被解释为整数类型,而是作为字节序列来处理。bytes也可以存储其他数据类型,比如字符串==

引用类型初始值

映射mapping: 所有元素都为其默认值的mapping

  • 结构体struct: 所有成员设为其默认值的结构体
  • 数组array
    • 动态数组: []
    • 静态数组(定长): 所有成员设为其默认值的静态数组

可以用public变量的getter函数验证上面写的初始值是否正确:

1
2
3
4
5
6
7
8
9
10
// Reference Types
uint[8] public _staticArray; // 所有成员设为其默认值的静态数组[0,0,0,0,0,0,0,0]
uint[] public _dynamicArray; // `[]`
mapping(uint => address) public _mapping; // 所有元素都为其默认值的mapping
// 所有成员设为其默认值的结构体 0, 0
struct Student{
uint256 id;
uint256 score;
}
Student public student;

delete操作符

delete a会让变量a的值变为初始值。

1
2
3
4
5
// delete操作符
bool public _bool2 = true;
function d() external {
delete _bool2; // delete 会让_bool2变为默认值,false
}

在remix上验证

  • 部署合约查看值类型、引用类型的初始值

    img

  • 值类型、引用类型delete操作后的默认值

    img

总结

这一讲,我们介绍了solidity中变量的初始值。变量被声明但没有赋值的时候,它的值默认为初始值。不同类型的变量初始值不同,delete操作符可以删除一个变量的值并代替为初始值。

Solidity极简入门: 9. 常数 constant和immutable

这一讲,我们介绍solidity中两个关键字,constant(常量)和immutable(不变量)。状态变量声明这个两个关键字之后,不能在合约后更改数值;并且还可以==节省gas==。另外,只有数值变量可以声明constantimmutable;==stringbytes可以声明为constant,但不能为immutable。==

constant和immutable

constant

==constant变量必须在声明的时候初始化,之后再也不能改变。尝试改变的话,编译不通过。string和bytes必须用constant==

1
2
3
4
5
// constant变量必须在声明的时候初始化,之后不能改变
uint256 constant CONSTANT_NUM = 10;
string constant CONSTANT_STRING = "0xAA";
bytes constant CONSTANT_BYTES = "WTF";
address constant CONSTANT_ADDRESS = 0x0000000000000000000000000000000000000000;

immutable

immutable变量可以在声明时或构造函数中初始化,因此更加灵活。

1
2
3
4
5
// immutable变量可以在constructor里初始化,之后不能改变
uint256 public immutable IMMUTABLE_NUM = 9999999999;
address public immutable IMMUTABLE_ADDRESS;
uint256 public immutable IMMUTABLE_BLOCK;
uint256 public immutable IMMUTABLE_TEST;

你可以使用全局变量例如address(this)block.number ,或者自定义的函数给immutable变量初始化。在下面这个例子,我们利用了test()函数给IMMUTABLE_TEST初始化为9

1
2
3
4
5
6
7
8
9
10
11
// 利用constructor初始化immutable变量,因此可以利用
constructor(){
IMMUTABLE_ADDRESS = address(this);
IMMUTABLE_BLOCK = block.number;
IMMUTABLE_TEST = test();
}

function test() public pure returns(uint256){
uint256 what = 9;
return(what);
}

在remix上验证

  1. 部署好合约之后,通过remix上的getter函数,能获取到constantimmutable变量初始化好的值。

    9-1.png

  2. constant变量初始化之后,尝试改变它的值,会编译不通过并抛出TypeError: Cannot assign to a constant variable.的错误。

9-2.png

  1. immutable变量初始化之后,尝试改变它的值,会编译不通过并抛出TypeError: Immutable state variable already initialized.的错误。

    9-3.png

总结

这一讲,我们介绍solidity中两个关键字,constant(常量)和immutable(不变量),让不应该变的变量保持不变。这样的做法能在节省gas的同时提升合约的安全性。