在前文我们讲过 Solidity 是一种静态类型
的语言,这就意味着在声明变量前需先指定类型。
而 Solidity 对变量划分了以下三种作用域
范围:
- 状态变量(State Variable):
该变量的值被永久地存放在合约存储中,合约内所有函数可访问,其Gas(燃料)
消耗高。
- 局部变量(Local Variable):
函数体声明的变量,其值在该函数执行前都存在的变量。
- 全局变量(Global Variable):
存在于全局命名空间的特殊变量
,提供有关区块链和交易属性的信息。
状态变量(State Variable)
其值被永久地存放在一个合约存储中。
pragma solidity ^0.8.0;
contract SolidityTest {
uint storedData; // 状态变量(State variable)
//这是构造器函数
constructor() public {
storedData = 10; // 使用 状态变量
}
}
局部变量(Local Variable):
声明变量在函数体的变量,其值在函数执行前一直存在。
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract SolidityTest {
uint storedData; // 状态变量
//构造器函数
constructor() public {
storedData = 10;
}
//声明一个函数
function getResult() public view returns(uint){
uint a = 1; // 局部变量(local variable)
uint b = 2;
uint result = a + b;
return result; //返回 局部变量
}
}
我们做些小改动,让函数返回 状态变量,会是什么样的结果呢?
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract SolidityTest {
uint storedData; // 状态变量
//构造器函数
constructor() public {
storedData = 10;
}
//声明一个函数
function getResult() public view returns(uint){
uint a = 1; // 局部变量(local variable)
uint b = 2;
uint result = a + b;
return storedData; //返回 状态变量
}
}
您可能也注意到,编译图标下有 2 个警告。
针对第一个警告,那是 Solidity 0.7 版本之后对 构造器 的 可见修饰忽略了,解决办法:便是删除它。
而 第二个 警告 便是声明过的变量没有使用,这点倒是和 golang 很像,但在 Solidity 中并没有那么严格,只是给出警告提示,还是可以编译的,在这里建议,去掉没使用的变量。
全局变量(Global Variable)
存在全局工作区的特俗变量,用于提供区块链和交易的属性。
Name | Returns |
---|---|
blockhash(uint blockNumber) returns (bytes32) | Hash of the given block - only works for 256 most recent, excluding current, blocks |
block.coinbase (address payable) | Current block miner’s address |
block.difficulty (uint) | Current block difficulty |
block.gaslimit (uint) | Current block gaslimit |
block.number (uint) | Current block number |
block.timestamp (uint) | Current block timestamp as seconds since unix epoch |
gasleft() returns (uint256) | Remaining gas |
msg.data (bytes calldata) | Complete calldata |
msg.sender (address payable) | Sender of the message (current caller) |
msg.sig (bytes4) | First four bytes of the calldata (function identifier) |
msg.value (uint) | Number of wei sent with the message |
now (uint) | Current block timestamp |
tx.gasprice (uint) | Gas price of the transaction |
tx.origin (address payable) | Sender of the transaction |
blockhash(uint blockNumber) returns (bytes32)
:指定区块的区块哈希 —— 仅可用于最新的 256 个区块且不包括当前区块,否则返回 0 。block.basefee
(uint
): 当前区块的基础费用block.chainid
(uint
): 当前链 idblock.coinbase
(address
): 挖出当前区块的矿工地址block.difficulty
(uint
): 当前区块难度block.gaslimit
(uint
): 当前区块 gas 限额block.number
(uint
): 当前区块号block.timestamp
(uint
): 自 unix epoch 起始当前区块以秒计的时间戳gasleft() returns (uint256)
:剩余的 gasmsg.data
(bytes
): 完整的 calldatamsg.sender
(address
): 消息发送者(当前调用)msg.sig
(bytes4
): calldata 的前 4 字节(也就是函数标识符)msg.value
(uint
): 随消息发送的 wei 的数量tx.gasprice
(uint
): 交易的 gas 价格tx.origin
(address
): 交易发起者(完全的调用链)
标识符
与众多编程语言一样,在您声明 Solidity 变量名称时,请不要使用 Solidity 保留关键字,如break
、boolean
变量名是无效的。
Solidity 标识符一样也是由字母
、下划线
和数字
组成的,注意:不要以数字
开头来命名变量名。
在 Solidity 中,标识符是区分大小写的,如:name
和Name
是两个不同的变量名哦!
变量作用范围
局部变量(Local Variable)的范围仅限于它们被定义的函数,但 状态变量(State Variable) 可以有三种范围。
public - public 修饰的 状态变量(State Variable) 可以在内部以及通过消息进行访问,对于一个公共状态变量,会自动生成一个getter函数。
internal: internal(内部) 修饰的 状态变量(State Variable) 只能在内部从当前的合约或从它派生的合约中访问。
private:private 修饰的 状态变量(State Variable)只能从当前的合同内部访问,其派生类不能访问。
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract C {
uint public data = 30;
uint internal iData= 10;
uint private pData = 5;
function x() public returns (uint) {
data = 3; // internal(内部)
pData = 7; //可以使用
return data;
}
}
contract Caller {
C c = new C();
function f() public view returns (uint) {
//c.pData = 11; 报错 错误提示 变量不可见
return c.data(); //external (外部)
}
}
//合约 D 继承了合约 C 后续会讲到
contract D is C {
function y() public returns (uint) {
iData = 3; // internal (内部)
// pData = 4; 报错 错误提示变量未定义
return iData;
}
function getResult() public pure returns(uint){
uint a = 1; // 局部变量(local variable)
uint b = 2;
uint result = a + b;
return result; //状态变量(state variable)
}
}