【问题标题】:Function calls function in GoGo中的函数调用函数
【发布时间】:2018-04-10 14:46:17
【问题描述】:
package main

var a string

func main() {
   a = "G"
   print(a)
   f1()
}

func f1() {
   a := "O"
   print(a)
   f2()
}

func f2() {
   print(a)
}

我认为在f1 中调用f2f2 将在f1 的块中,因此输出将为GOO,但输出为GOG

在函数内声明的类型标识符的范围从 TypeSpec 中的标识符开始,到最里面的包含块的末尾结束。 -- 来自https://golang.org/ref/spec#Declarations_and_scope

函数中包含哪些块?

为什么另一个函数不包含块?

【问题讨论】:

  • 这里的包含块是定义函数的块,而不是调用函数的块。大多数块都以{ } 为框架。

标签: go scope


【解决方案1】:

您的函数 f1 创建了一个新的局部变量 a,它隐藏全局变量 a

func f1() {
   a := "O"
   print(a)
   f2()
}

该变量的范围为f1。它调用的任何函数都有自己的范围,f1 内的任何范围更改都不会影响它调用的任何其他函数(闭包除外)。因此,当f2 访问a 时,它正在访问全局 a。否则,几乎不可能确定行为,因为它完全取决于调用上下文,调用上下文在对同一函数的不同调用之间可能会有所不同。如果你想将一些值传递给函数,请将其作为参数传递。

【讨论】:

  • 所以函数的作用域是current global scope + current function's own scope'?如果你想改变被调用函数的作用域,你可以改变全局作用域或者被调用函数的作用域。
  • 你不能改变被调用函数的作用域。您可以修改现有全局变量的值,并且函数(无论如何调用)可以创建新的局部变量,这可能会影响全局变量。
【解决方案2】:

在同一段中它还说:

在块中声明的标识符可以在内部块中重新声明。 虽然内部声明的标识符在范围内,但它表示 内部声明所声明的实体。

因此答案应该是“GOG”。

【讨论】:

    【解决方案3】:

    函数中包含的块是任何控制结构,例如ifforswitch

    函数可以包含变量块。在您的示例中,f1 是一个包含块,因为它重新声明了 a 并隐藏了全局声明。

    f2 不在f1s 块中。它们在同一级别上声明。但是你可以在另一个函数中定义一个函数:

    func f1() {
        a := "a1" // f1 is containig block for a
        f2 := func () {
            // a is visible here, too
            b := "b" // f2 is containing block for b, only visible in f2
        }
    }
    

    【讨论】:

    • A function is a containing block 是否声明或隐藏任何变量。您的后一个示例称为closure
    • 我没有说别的,但我改变了我的答案,让它更清楚一点。感谢您的输入。整个示例包含一个闭包,但它不是一个很好的闭包示例。这个话题有点跑题了。
    【解决方案4】:

    要理解这个问题,我认为你应该首先意识到What happens when a function is called

    f1调用f2时,f1的返回地址、f2的参数和locals将被添加到堆栈中。所以f2 只能访问它的本地和当前的全局。

    f1 中的 a := "O" 仅更新 f1 的局部变量,不影响全局变量。所以f2 将从全局变量中读取a(值与G 相同)。

    总而言之,当在f1中调用f2()时,f2()f1的块中,但是当进入f2时,f1的块与f2无关。

    【讨论】:

      【解决方案5】:

      您正在 f1() 中创建一个新变量“a” 试试这个:

      package main
      
      var a string
      
      func main() {
          a = "G"
          print(a)
          f1()
      }
      
      func f1() {
          a = "O"
          print(a)
          f2()
       }
      
      func f2() {
          print(a)
      }
      

      通过在 '=' 之前删除 ':' 您将引用全局变量

      【讨论】:

        猜你喜欢
        • 2011-09-01
        • 1970-01-01
        • 2019-03-30
        • 2019-09-18
        • 2021-01-28
        • 1970-01-01
        • 2015-02-14
        • 2019-04-17
        • 2020-02-01
        相关资源
        最近更新 更多