WTF Solidity 入门教程(西班牙语版)第 3 讲:Solidity 函数类型完全指南——pure、view、payable 与可见性 WTF Solidity 入门教程西班牙语版第 3 讲Solidity 函数类型完全指南——pure、view、payable 与可见性【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity本讲是 WTF Solidity 极简入门系列的第 3 课围绕 Solidity 中函数function的完整语法展开四种可见性说明符internal/external/public/private、行为修饰关键字pure/view/payable以及返回值returns。通过本讲读者将掌握如何声明一个合法且高效的 Solidity 函数理解pure/view与链上 gas 成本的深层关系并能对照 Function.sol 源码逐一验证每种函数类型的实际行为。函数Solidity 中最核心的构件在 Solidity 中函数是合约与外部世界交互的唯一入口也是状态读写、资金收付、事件释放等一切操作的载体。与其他编程语言相比Solidity 的函数声明多出了可见性说明符与行为修饰符这是由区块链执行模型的特殊性决定的每一个函数调用都可能触发链上状态变更并消耗真金白银的 gas。因此正确地声明函数类型是写出安全、经济合约的第一步。函数声明的完整语法模板先看 Solidity 中函数的标准形式方括号[ ]内的关键字是可选的function nombre de la función(tipos de los parámetros) {internal|external|public|private} [pure|view|payable] [returns (tipos de retorno)]这个模板看起来复杂其实可以从前往后逐段拆解function声明函数的固定关键字任何函数都必须以它开头。nombre de la función函数名遵循 Solidity 标识符命名规则。(tipos de los parámetros)圆括号内写入函数的输入参数即参数的类型与名称。没有参数时保留空的()。{internal|external|public|private}函数可见性说明符四选一详见下一节。[pure|view|payable]决定函数权限与行为的关键字。payable可支付很好理解带有它的函数在运行时可以接收转入合约的ETHpure和view则与链上状态读写有关单独成节讲解。[returns (tipos de retorno)]函数的返回值类型与名称有返回值时不能省略。在仓库的 Function.sol 中还可以看到该模板在注释中的体现以及一个容易被忽略的细节——合约还声明了constructor() payable {}允许在部署合约的同时向其转入ETH为后续payable函数演示提供初始余额基础。四种可见性说明符详解可见性说明符必须显式指定它决定了谁能调用该函数public所有人可见。既可以被合约内部调用也可以被外部账户或合约调用。private只能从本合约内部访问继承该合约的子合约也不能使用。external只能从合约外部调用但在合约内部可以通过this.f()的形式调用f为函数名。internal只能从合约内部访问但继承该合约的子合约可以使用。围绕可见性原教程给出了三条必须牢记的注意点注意 1合约中定义的函数没有默认可见性必须显式写明public、private、internal或external否则编译报错。注意 2public/private/internal同样可以修饰状态变量状态变量的概念可参考本仓库 05_DataStorage 一讲。被public修饰的状态变量会自动生成一个同名的getter函数用于外部查询其数值。注意 3未标注可见性类型的状态变量默认可见性为internal。到底什么是pure和view初学 Solidity 时pure与view往往令人困惑因为其他编程语言中没有类似的关键字。Solidity 引入这两个关键字根本原因是以太坊交易需要支付 gas 费用合约的状态变量存储在链上读写链上状态的开销极高。如果一个函数的计算不改变链上状态用户直接调用它就不需要支付 gas注意若由合约内其他非pure/view函数在链上调用它们则依然需要支付 gas。在以太坊中以下语句被视为修改链上状态凡涉及这些操作的函数都不能声明为pure或view写入状态变量。释放事件emit。创建其他合约。使用selfdestruct。通过函数调用发送以太币。调用任何未标记为view或pure的函数。使用低级调用low-level calls如call、delegatecall。使用包含某些操作码opcode的内联汇编assembly。为了让抽象概念更直观本讲用马里奥游戏角色做了经典比喻合约的状态变量存储在链上好比碧琪公主三种不同的角色代表不同的函数关键字——pure纯净既不能读取也不能写入链上的状态变量。如同小怪看不到也摸不到碧琪公主。view观看能读取但不能写入链上的状态变量。如同马里奥能看到碧琪公主但终究只能做看客。不带pure或view的函数既可以读取也可以写入状态变量如同关卡中的 boss为所欲为。代码演示一pure 与 view 的边界在合约中定义状态变量number初始化为 5// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract FunctionTypes{ uint256 public number 5; }定义一个add()函数每次调用让number增加 1// default默认函数可读写状态 function add() external{ number number 1; }如果给add()加上pure写成function add() external pure必然编译报错——因为pure函数既不配读取、更不配改写合约中的状态变量。那pure函数能做什么答案是只处理传入的参数并返回计算结果。例如传入一个参数_number让它返回_number 1全程不触碰状态变量// pure既不写链上数据也不读链上数据 function addPure(uint256 _number) external pure returns(uint256 new_number){ new_number _number 1; }调用addPure(1)会直接得到返回值2且该调用发生在链下不消耗 gas如下图所示同理如果给add()加上view写成function add() external view同样编译报错——因为view能读取但不能改写状态变量。正确写法是读取number但不改写它返回一个新的变量// view可以读但不能写 function addView() external view returns(uint256 new_number) { new_number number 1; }对比addPure与addView可以发现关键区别addView直接读取了链上状态变量number初始为 5因此返回 6而addPure完全依赖外部传入的参数。代码演示二internal 与 external 的配合// internal内部函数 function minus() internal { number number - 1; } // 合约内的函数可以调用内部函数 function minusCall() external { minus(); }这里定义了一个internal的minus()函数每次调用使number减少 1。由于internal函数只能被合约内部调用外部账户无法直接触发因此必须再定义一个external的minusCall()函数由它间接调用内部的minus()。这也展示了 Solidity 常见的外部入口 内部逻辑封装模式把敏感逻辑设为internal或private通过受控的external/public函数暴露给外部代码演示三payable 函数与合约余额// payable可通过该函数向合约转入 ETH function minusPayable() external payable returns(uint256 balance) { minus(); balance address(this).balance; }这里定义了一个external payable的minusPayable()函数它内部调用minus()使number减 1并返回合约当前的ETH余额。其中的this关键字用于引用当前合约地址address(this).balance即当前合约持有的ETH总量。由于函数带有payable关键字调用minusPayable()时可以同时向合约转入 1 个ETH从返回信息中可以看到合约余额变为了对应的ETH数量。这正是payable的用途它是合约接收资金的标准入口凡涉及收款如铸造 NFT、代币申购、捐款等的函数都必须声明为payable否则转入的ETH会被拒绝。仓库源码级对照验证将上面的片段合并在 Function.sol 中即得到完整可编译的合约中文原版见 03_Function/Function.sol。值得注意的是当前仓库中的源码将pragma声明为^0.8.34并额外加入了constructor() payable {}允许部署时即向合约注入ETH。逐个函数对照add()无pure/view修饰可读可写number每次调用消耗 gas 且状态上链。addPure(uint256)不读不写状态只做纯计算外部调用免费。addView()读取number但不上链改写外部调用免费。minus()internal只能被合约内部调用。minusCall()external入口转发调用minus()。minusPayable()external payable可接收ETH并返回address(this).balance。从源码结构看这六种函数类型构成了 Solidity 函数语义的最小完备示例可见性控制访问范围pure/view控制状态读写权限payable控制资金接收能力。三者正交组合即可表达绝大多数合约函数的权限模型。总结本讲完整介绍了 Solidity 中的函数类型。核心要点可以浓缩为三句话函数必须显式声明可见性internal/external/public/private状态变量默认为internalpublic状态变量会自动生成getter。view函数可以读取但不能改写状态变量pure函数既不能读取也不能改写状态变量这两类函数外部直接调用时不需要支付 gas。payable函数是合约接收ETH的入口配合this与address(this).balance可以查询合约资金余额。理解pure与view的关键在于理解它们与链上状态和 gas 的关系——这是 Solidity 区别于其他语言、也是写出高效低耗合约的基础所在。【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考