函数基础 #
一、函数定义 #
1.1 基本语法 #
solidity
function functionName(parameters) visibility modifier returns (returnTypes) {
// 函数体
}
1.2 函数组成 #
| 组成部分 | 说明 | 示例 |
|---|---|---|
| function | 函数关键字 | function |
| functionName | 函数名 | transfer |
| parameters | 参数列表 | (address to, uint256 amount) |
| visibility | 可见性 | public, private, internal, external |
| modifier | 状态修饰符 | view, pure, payable |
| returns | 返回值 | returns (bool) |
1.3 基本示例 #
solidity
contract FunctionBasics {
// 无参数无返回值
function sayHello() public pure {
// 纯函数,不读取也不修改状态
}
// 有参数无返回值
function setValue(uint256 value) public {
// 修改状态
}
// 无参数有返回值
function getValue() public view returns (uint256) {
// 读取状态
return 0;
}
// 有参数有返回值
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
}
二、函数参数 #
2.1 参数传递 #
solidity
contract FunctionParameters {
// 单个参数
function singleParam(uint256 value) public pure returns (uint256) {
return value;
}
// 多个参数
function multipleParams(
uint256 a,
uint256 b,
uint256 c
) public pure returns (uint256) {
return a + b + c;
}
// 不同类型参数
function mixedParams(
address user,
uint256 amount,
bool isActive,
string memory name
) public pure returns (string memory) {
if (isActive) {
return name;
}
return "";
}
}
2.2 引用类型参数 #
solidity
contract ReferenceTypeParams {
// memory参数
function processArray(uint256[] memory arr) public pure returns (uint256) {
uint256 sum = 0;
for (uint256 i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
// calldata参数(只读,更省Gas)
function processCalldata(uint256[] calldata arr) public pure returns (uint256) {
uint256 sum = 0;
for (uint256 i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
// storage参数
uint256[] public data;
function modifyStorage(uint256[] storage arr) internal {
arr.push(1);
}
}
2.3 参数命名 #
solidity
contract ParameterNaming {
// 推荐:使用下划线前缀区分参数和状态变量
uint256 public balance;
function setBalance(uint256 _balance) public {
balance = _balance;
}
// 或者使用不同的名称
function updateBalance(uint256 newBalance) public {
balance = newBalance;
}
}
三、返回值 #
3.1 单返回值 #
solidity
contract SingleReturn {
// 显式返回
function getOne() public pure returns (uint256) {
return 1;
}
// 命名返回值
function getTwo() public pure returns (uint256 result) {
result = 2;
// 可以省略return语句
}
// 使用return
function getThree() public pure returns (uint256 result) {
return 3;
}
}
3.2 多返回值 #
solidity
contract MultipleReturns {
// 多个返回值
function getMultiple() public pure returns (uint256, bool, string memory) {
return (1, true, "Hello");
}
// 命名多返回值
function getNamed() public pure returns (
uint256 number,
bool flag,
string memory text
) {
number = 1;
flag = true;
text = "Hello";
}
// 解构赋值
function destructuring() public pure returns (uint256) {
(uint256 a, bool b, string memory c) = getMultiple();
return a;
}
// 忽略部分返回值
function ignoreReturn() public pure returns (uint256) {
(uint256 a, , ) = getMultiple(); // 忽略后两个返回值
return a;
}
}
3.3 返回数组和结构体 #
solidity
contract ReturnComplexTypes {
struct User {
address wallet;
string name;
uint256 balance;
}
// 返回数组
function getNumbers() public pure returns (uint256[] memory) {
uint256[] memory arr = new uint256[](3);
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
return arr;
}
// 返回结构体
function getUser() public pure returns (User memory) {
return User({
wallet: msg.sender,
name: "Alice",
balance: 100
});
}
// 返回结构体数组
function getUsers() public pure returns (User[] memory) {
User[] memory users = new User[](2);
users[0] = User(msg.sender, "Alice", 100);
users[1] = User(msg.sender, "Bob", 200);
return users;
}
}
四、可见性 #
4.1 public #
solidity
contract PublicFunction {
uint256 public value; // public状态变量自动生成getter
// public函数:任何地方都可以调用
function setValue(uint256 _value) public {
value = _value;
}
function getValue() public view returns (uint256) {
return value;
}
}
// 外部调用
contract ExternalCaller {
PublicFunction public target;
function callPublic() public view returns (uint256) {
return target.getValue(); // 可以调用public函数
}
}
4.2 private #
solidity
contract PrivateFunction {
uint256 private value;
// private函数:只有本合约可以调用
function _internalLogic() private pure returns (uint256) {
return 1;
}
function publicFunction() public pure returns (uint256) {
return _internalLogic(); // 本合约可以调用
}
}
// 子合约无法访问private
contract ChildContract is PrivateFunction {
function tryAccessPrivate() public pure returns (uint256) {
// return _internalLogic(); // 错误:无法访问
return 0;
}
}
4.3 internal #
solidity
contract InternalFunction {
uint256 internal value;
// internal函数:本合约和子合约可以调用
function _internalFunction() internal pure returns (uint256) {
return 1;
}
function publicFunction() public pure returns (uint256) {
return _internalFunction();
}
}
// 子合约可以访问internal
contract ChildInternal is InternalFunction {
function accessInternal() public pure returns (uint256) {
return _internalFunction(); // 可以访问
}
}
4.4 external #
solidity
contract ExternalFunction {
uint256 private value;
// external函数:只能从外部调用
function externalFunction() external view returns (uint256) {
return value;
}
// 本合约内调用external函数需要使用this
function callExternal() public view returns (uint256) {
return this.externalFunction(); // 通过this调用
}
}
// 外部调用
contract ExternalCaller {
ExternalFunction public target;
function callExternal() public view returns (uint256) {
return target.externalFunction();
}
}
4.5 可见性对比 #
| 可见性 | 本合约 | 子合约 | 外部合约 |
|---|---|---|---|
| public | ✓ | ✓ | ✓ |
| private | ✓ | ✗ | ✗ |
| internal | ✓ | ✓ | ✗ |
| external | ✗* | ✗* | ✓ |
*注:external可以通过this.functionName()在本合约内调用
五、状态修饰符 #
5.1 view #
solidity
contract ViewFunction {
uint256 public value = 100;
// view:只读,不修改状态
function getValue() public view returns (uint256) {
return value; // 读取状态
}
function calculate(uint256 a) public view returns (uint256) {
return a + value; // 读取状态,但不修改
}
// view函数不能修改状态
// function badView() public view {
// value = 1; // 错误:不能修改状态
// }
}
5.2 pure #
solidity
contract PureFunction {
// pure:不读取也不修改状态
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
return a * b;
}
// pure函数不能读取或修改状态
uint256 public value = 100;
// function badPure() public pure returns (uint256) {
// return value; // 错误:不能读取状态
// }
}
5.3 payable #
solidity
contract PayableFunction {
mapping(address => uint256) public balances;
event Deposit(address indexed from, uint256 amount);
// payable:可以接收ETH
function deposit() public payable {
require(msg.value > 0, "Must send ETH");
balances[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
// 非payable函数不能接收ETH
function noPayable() public {
// 如果发送ETH会revert
}
// 查询合约余额
function getBalance() public view returns (uint256) {
return address(this).balance;
}
}
5.4 状态修饰符对比 #
| 修饰符 | 读取状态 | 修改状态 | 接收ETH |
|---|---|---|---|
| 无修饰 | ✓ | ✓ | ✗ |
| view | ✓ | ✗ | ✗ |
| pure | ✗ | ✗ | ✗ |
| payable | ✓ | ✓ | ✓ |
六、函数重载 #
6.1 基本重载 #
solidity
contract FunctionOverloading {
// 同名函数,不同参数
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
function add(uint256 a, uint256 b, uint256 c) public pure returns (uint256) {
return a + b + c;
}
function add(int256 a, int256 b) public pure returns (int256) {
return a + b;
}
}
6.2 重载解析 #
solidity
contract OverloadResolution {
function process(uint256 value) public pure returns (string memory) {
return "uint256";
}
function process(address value) public pure returns (string memory) {
return "address";
}
function process(bool value) public pure returns (string memory) {
return "bool";
}
// 调用时根据参数类型选择
function test() public pure returns (string memory, string memory, string memory) {
return (
process(uint256(1)),
process(address(0)),
process(true)
);
}
}
七、实际应用示例 #
7.1 代币合约 #
solidity
contract SimpleToken {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
uint256 _totalSupply
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
totalSupply = _totalSupply;
balanceOf[msg.sender] = _totalSupply;
}
function transfer(address to, uint256 amount) public returns (bool) {
require(to != address(0), "Invalid recipient");
require(balanceOf[msg.sender] >= amount, "Insufficient balance");
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
require(spender != address(0), "Invalid spender");
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public returns (bool) {
require(from != address(0), "Invalid from");
require(to != address(0), "Invalid to");
require(balanceOf[from] >= amount, "Insufficient balance");
require(allowance[from][msg.sender] >= amount, "Insufficient allowance");
balanceOf[from] -= amount;
balanceOf[to] += amount;
allowance[from][msg.sender] -= amount;
emit Transfer(from, to, amount);
return true;
}
}
八、最佳实践 #
8.1 函数命名 #
solidity
contract FunctionNaming {
// 推荐:使用动词开头
function getBalance() public view returns (uint256) {}
function setBalance(uint256 _balance) public {}
function transfer(address to, uint256 amount) public {}
function calculateInterest() public pure returns (uint256) {}
// 推荐:内部函数使用下划线前缀
function _validateAddress(address _addr) internal pure returns (bool) {
return _addr != address(0);
}
// 推荐:私有函数使用下划线前缀
function _internalLogic() private pure returns (uint256) {
return 1;
}
}
8.2 函数长度 #
solidity
contract FunctionLength {
// 不推荐:过长的函数
function badLongFunction(
address a,
uint256 b,
bool c,
string memory d
) public pure returns (uint256, bool, string memory) {
// 100行代码...
return (0, false, "");
}
// 推荐:拆分为多个小函数
function goodShortFunction(address a, uint256 b) public pure returns (uint256) {
_validateInput(a, b);
return _processData(a, b);
}
function _validateInput(address a, uint256 b) internal pure {
require(a != address(0), "Invalid address");
require(b > 0, "Invalid amount");
}
function _processData(address a, uint256 b) internal pure returns (uint256) {
return b;
}
}
九、总结 #
函数基础要点:
| 组成部分 | 说明 |
|---|---|
| 参数 | 输入数据,支持多种类型 |
| 返回值 | 输出数据,支持多返回值 |
| 可见性 | public/private/internal/external |
| 状态修饰符 | view/pure/payable |
使用建议:
- 使用有意义的函数名
- 保持函数简洁
- 选择正确的可见性
- 使用view/pure减少Gas消耗
接下来,让我们学习函数修饰符!
最后更新:2026-03-27