Function
本节是《Solidity by Example》的中文翻译与深入讲解,专为零基础或刚接触区块链开发的小白朋友打造。我们将通过“示例 + 解说 + 提示”的方式,带你逐步理解每一段 Solidity 代码的实际用途与背后的逻辑。
Solidity 是以太坊等智能合约平台使用的主要编程语言,就像写网页要用 HTML 和 JavaScript,写智能合约就需要会 Solidity。
如果你从没写过区块链代码也没关系,只要你了解一点点编程概念,比如“变量”“函数”“条件判断”,我们就能从最简单的例子开始,一步步建立你的 Solidity 编程思维。
Function
函数
函数可以通过多种方式返回输出。
公共函数不能接受某些数据类型作为输入或输出。
-
什么是 Solidity 函数?
在 Solidity 中,函数是智能合约的核心组件,用于执行逻辑、操作数据或与区块链交互。
- 比喻:函数像一台机器,输入原材料(参数),输出产品(返回值),并可能改变机器状态(区块链数据)。
- 函数可以定义访问权限(如
public
、external
)、状态修改行为(如view
、pure
)以及输入输出类型。
-
返回输出的多种方式:
- 多返回值:函数可以返回多个值(如
uint256
和bool
)。 - 命名返回值:返回值可以命名,简化代码(省略
return
语句)。 - 解构赋值:调用其他函数的多返回值时,可以用解构赋值接收部分或全部值。
- 多返回值:函数可以返回多个值(如
-
输入输出的限制:
- 公共函数(
public
):- 不能接受某些复杂类型(如
mapping
)作为输入或输出,因为这些类型无法通过外部调用序列化。 - 支持数组(
array
)作为输入或输出,但需指定数据位置(如memory
)。
- 不能接受某些复杂类型(如
- 其他访问权限:
external
:仅限外部调用,适合优化 Gas。internal
/private
:支持更复杂类型(如mapping
),但仅限合约内部或继承合约调用。
- 公共函数(
// SPDX-License-Identifier: MIT
// 使用 MIT 许可证,允许自由使用、修改和分发代码。pragma solidity ^0.8.26;
// 指定 Solidity 编译器版本,必须为 0.8.26 或更高(但低于 0.9.0)。contract Function {// 定义一个名为 Function 的智能合约,展示函数的多种用法。// Functions can return multiple values.// 函数可以返回多个值。function returnMany() public pure returns (uint256, bool, uint256) {return (1, true, 2);// 定义一个公共函数 returnMany,返回三个值:uint256、bool 和 uint256。// public:可被外部和内部调用。// pure:不读取或修改区块链状态,链下调用免费。// 返回值:1(uint256)、true(bool)、2(uint256)。}// Return values can be named.// 返回值可以命名。function named() public pure returns (uint256 x, bool b, uint256 y) {return (1, true, 2);// 定义一个公共函数 named,返回三个命名值:x(uint256)、b(bool)、y(uint256)。// 命名返回值会自动声明同名变量,函数体内可直接使用。// 返回值与 returnMany 相同,效果一致。}// Return values can be assigned to their name.// 返回值可以直接赋值给命名变量。// In this case the return statement can be omitted.// 在这种情况下,可以省略 return 语句。function assigned() public pure returns (uint256 x, bool b, uint256 y) {x = 1;b = true;y = 2;// 定义一个公共函数 assigned,返回三个命名值:x、b、y。// 直接为命名变量赋值(x、b、y),无需显式 return。// 函数结束时,Solidity 自动返回命名变量的值(1, true, 2)。}// Use destructuring assignment when calling another// function that returns multiple values.// 调用返回多个值的函数时,使用解构赋值。function destructuringAssignments() public pure returns (uint256, bool, uint256, uint256, uint256){(uint256 i, bool b, uint256 j) = returnMany();// 调用 returnMany(),返回 (1, true, 2),通过解构赋值存储到 i、b、j。// 解构赋值允许接收全部或部分返回值。// Values can be left out.// 可以省略部分值。(uint256 x,, uint256 y) = (4, 5, 6);// 直接解构赋值一个元组 (4, 5, 6),存储到 x(4)和 y(6),中间值 5 被忽略(用 ,, 表示)。return (i, b, j, x, y);// 返回五个值:i(1)、b(true)、j(2)、x(4)、y(6)。}// Cannot use map for either input or output// 不能将映射(mapping)用作输入或输出。// (注释说明 public 函数不支持 mapping 作为参数或返回值,因为 mapping 无法序列化。)// Can use array for input// 可以将数组用作输入。function arrayInput(uint256[] memory _arr) public {}// 定义一个公共函数 arrayInput,接受 memory 类型的 uint256 数组 _arr。// memory:数组是临时数据,函数结束后销毁。// 空函数体,仅展示数组作为输入的可行性。// Can use array for output// 可以将数组用作输出。uint256[] public arr;// 声明一个公共的动态数组 arr,存储在 storage(区块链上)。// public 自动生成 getter 函数(arr(uint256))。function arrayOutput() public view returns (uint256[] memory) {return arr;// 定义一个公共函数 arrayOutput,返回 memory 类型的 uint256 数组。// view:只读取区块链状态(arr),不修改,链下调用免费。// 返回 arr 的副本(memory 类型),不影响原 storage 数据。}
}
contract XYZ {// 定义一个名为 XYZ 的智能合约,展示复杂函数调用。function someFuncWithManyInputs(uint256 x,uint256 y,uint256 z,address a,bool b,string memory c) public pure returns (uint256) {}// 定义一个公共函数 someFuncWithManyInputs,接受多个参数:// - x, y, z:uint256 类型。// - a:address 类型。// - b:bool 类型。// - c:string 类型,memory 存储。// pure:不访问区块链状态,空函数体仅用于展示多参数输入。function callFunc() external pure returns (uint256) {return someFuncWithManyInputs(1, 2, 3, address(0), true, "c");// 定义一个外部函数 callFunc,调用 someFuncWithManyInputs。// external:仅限外部调用,优化 Gas。// 按参数顺序传入:1, 2, 3, address(0), true, "c"。// 返回值由 someFuncWithManyInputs 决定(示例中为空,需实现逻辑)。}function callFuncWithKeyValue() external pure returns (uint256) {return someFuncWithManyInputs({a: address(0),b: true,c: "c",x: 1,y: 2,z: 3});// 定义一个外部函数 callFuncWithKeyValue,使用键值对方式调用 someFuncWithManyInputs。// 键值对调用允许无序指定参数(如先 a 后 x),提高可读性。// 参数值与 callFunc 相同,效果一致。}
}
代码包含两个合约,展示 Solidity 函数的多种返回方式、输入输出限制以及调用方式:
- 合约
Function
:- 展示多返回值、命名返回值、解构赋值以及数组作为输入输出的用法。
- 包含
pure
函数(不访问区块链状态)和view
函数(只读状态)。
- 合约
XYZ
:- 展示复杂函数调用,包括多参数函数、普通调用和键值对调用。
函数的本质
- 函数是 Solidity 合约的核心,用于执行逻辑、操作数据或与外部交互。
- 比喻:
- 函数像一个任务处理器,输入任务要求(参数),输出结果(返回值),可能改变合约状态(
storage
数据)。 returnMany
像一台机器,输入无参数,输出三个零件(1, true, 2)。named
和assigned
像给零件命名,方便工人(开发者)操作。destructuringAssignments
像从零件盒中挑出需要的零件。
- 函数像一个任务处理器,输入任务要求(参数),输出结果(返回值),可能改变合约状态(
- 核心功能:
- 多返回值:支持返回多个值(如
uint256, bool, uint256
)。 - 命名返回值:返回值命名后可直接赋值,省略
return
语句。 - 解构赋值:从其他函数或元组中提取部分返回值,灵活高效。
- 输入输出限制:
public
函数支持数组(需指定memory
),但不支持mapping
。 - 键值对调用:多参数函数可用键值对调用,参数顺序无关,提高可读性。
- 多返回值:支持返回多个值(如
代码功能
- 合约
Function
:returnMany()
:返回三个值 (1, true, 2),展示多返回值。named()
:命名返回值 (x, b, y),效果同returnMany
。assigned()
:通过命名变量赋值,返回 (1, true, 2),省略return
。destructuringAssignments()
:展示解构赋值,从returnMany
获取值并处理元组,返回 (1, true, 2, 4, 6)。arrayInput
:接受memory
数组,展示数组作为输入。arrayOutput
:返回memory
数组,读取storage
数组arr
的副本。
- 合约
XYZ
:someFuncWithManyInputs
:接受多个参数(uint256
、address
、bool
、string
),展示复杂输入。callFunc
:按顺序调用多参数函数。callFuncWithKeyValue
:用键值对调用多参数函数,参数顺序无关。
深入学习
- 函数类型:
pure
:不读写区块链状态,适合计算逻辑(如returnMany
)。view
:只读状态(如arrayOutput
),链下免费。- 无修饰符:可修改状态(如
updateArray
),消耗 Gas。
- Gas 优化:
- 使用
pure
和view
降低 Gas 成本。 - 键值对调用(
callFuncWithKeyValue
)比顺序调用略高 Gas,适合复杂参数时提高可读性。 - 数组参数用
memory
或calldata
(external
函数推荐calldata
更省 Gas)。
- 使用