• Solidity入门1: 3. 函数类型


    Solidity中的函数

    solidity官方文档里把函数归到数值类型

    函数结构
    function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]

    看着些复杂,咱们从前往后一个一个看(方括号中的是可写可不写的关键字):

    1. function声明函数时的固定用法,想写函数,就要以function关键字开头。

    2. 函数名。

    3. ()圆括号里写函数的参数,也就是要输入到函数的变量类型和名字。

    4. {internal|external|public|private}函数可见性说明符,一共4种。没标明函数类型的,默认public。合约之外的函数,即"自由函数",始终具有隐含internal可见性。

      • public: 内部外部均可见。
      • private: 只能从本合约内部访问,继承的合约也不能用。
      • external: 只能从合约外部访问(但是可以用this.f()来调用,f是函数名)。
      • internal: 只能从合约内部访问,继承的合约可以用。
    5. Note 1: 没有标明可见性类型的函数,默认为public

      Note 2public|private|internal 也可用于修饰状态变量。 public变量会自动生成同名的getter函数,用于查询数值。

      Note 3: 没有标明可见性类型的状态变量,默认为internal

    6. [pure|view|payable]决定函数权限/功能的关键字。payable(可支付的)很好理解,带着它的函数,运行的时候可以给合约转入ETH

    7. [returns ()]函数返回的变量类型和名称。

     

    到底什么是PureView

            我刚开始学solidity的时候,一直不理解pureview关键字,因为别的语言没有类似的关键字。solidity加入这两个关键字,我认为是因为gas fee。合约的状态变量存储在链上,gas fee很贵,如果不改变链上状态,就不用付gas。包含pureview关键字的函数是不改写链上状态的,因此用户直接调用他们是不需要付gas的(合约中非pure/view函数调用它们则会改写链上状态,需要付gas)。

    在以太坊中,以下语句被视为修改链上状态:

    1. 写入状态变量。
    2. 释放事件。
    3. 创建其他合约。
    4. 使用selfdestruct.
    5. 通过调用发送以太币。
    6. 调用任何未标记viewpure的函数。
    7. 使用低级调用(low-level calls)。
    8. 使用包含某些操作码的内联汇编。

            我画了一个马里奥插画,帮助大家理解。在插画里,我把合约中的状态变量(存储在链上)比作碧池公主,三种不同的角色代表不同的关键字。

    • pure,中文意思是“纯”,在solidity里理解为“纯纯牛马”。包含pure关键字的函数,不能读取也不能写入存储在链上的状态变量。就像小怪一样,看不到也摸不到碧池公主。

    • view,“看”,在solidity里理解为“看客”。包含view关键字的函数,能读取但也不能写入状态变量。类似马里奥,能看到碧池,但终究是看客,不能入洞房。

    • 不写pure也不写view,函数既可以读取也可以写入状态变量。类似马里奥里的boss,可以对碧池公主为所欲为🐶。

    代码

    1. pure 与 view的对比 

            我们在合约里定义一个状态变量 number = 5

    1. // SPDX-License-Identifier: MIT
    2. pragma solidity ^0.8.4;
    3. contract FunctionTypes{
    4. uint256 public number = 5;
    5. }

            定义一个add()函数,每次调用,每次给number + 1

    1. // 默认
    2. function add() external{
    3. number = number + 1;
    4. }

            如果add()包含了pure关键字,例如 function add() external pure就会报错。因为pure(纯纯牛马)是不配读取合约里的状态变量的,更不配改写。那pure函数能做些什么?

    举个例子,你可以给函数传递一个参数 _number,然后让他返回 _number+1

    1. // pure: 纯纯牛马
    2. function addPure(uint256 _number) external pure returns(uint256 new_number){
    3. new_number = _number + 1;
    4. }

            如果add()包含view,比如function add() external view也会报错。因为view能读取,但不能够改写状态变量。可以稍微改写下方程,让他不改写number,而是返回一个新的变量。

    1. // view: 看客
    2. function addView() external view returns(uint256 new_number) {
    3. new_number = number + 1;
    4. }

    2. internal v.s. external

    1. // internal: 内部
    2. function minus() internal {
    3. number = number - 1;
    4. }
    5. // 合约内的函数可以调用内部函数
    6. function minusCall() external {
    7. minus();
    8. }

    我们定义一个internalminus()函数,每次调用使得number变量减1。由于是internal,只能由合约内部调用,而外部不能。因此,我们必须再定义一个externalminusCall()函数,来间接调用内部的minus()。 

    Example:

    3、payable

    1. // payable: 递钱,能给合约支付eth的函数
    2. function minusPayable() external payable returns(uint256 balance) {
    3. minus();
    4. balance = address(this).balance;
    5. }

            我们定义一个external payableminusPayable()函数,间接的调用minus(),并且返回合约里的ETH余额(this关键字可以让我们引用合约地址)。 我们可以在调用minusPayable()时,往合约里转入1个ETH

    我们可以在返回的信息中看到,合约的余额是1 ETH。

    Example:

        本节介绍了solidity中的函数类型,比较难理解的是pureview,在其他语言中没出现过。solidity引入pureview关键字主要是为了节省gas和控制函数权限:如果用户直接调用pure/view方程是不消耗gas的(合约中非pure/view函数调用它们则会改写链上状态,需要付gas)。
     

  • 相关阅读:
    构建简单的梯度提升决策树(GBDT)模型:MATLAB 实现详解
    期货权益可用资金(期货的权益和可用资金)
    Linux常用命令字典篇
    【Linux】《Linux命令行与shell脚本编程大全 (第4版) 》笔记-Chapter18-图形化桌面环境中的脚本编程
    10道不得不会的Docker面试题
    KubeVela可持续测试应用部署之Mock基础设施
    探索性测试最佳实践
    如何利用Python中实现高效的网络爬虫
    使用Kubectl管理kubernetes集群
    dva详解 State、View、Action、connect、dispatch、Reducer
  • 原文地址:https://blog.csdn.net/djklsajdklsajdlk/article/details/137403542