函数基础 #

一、函数定义 #

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