Go中的函数调用函数

时间:2018-04-10 14:46:17

标签: go scope

package main

var a string

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

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

func f2() {
   print(a)
}

我认为在f2中调用f1时,f2会在f1块中,因此输出将为GOO,但而输出是GOG

  

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

函数中包含哪些块?

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

5 个答案:

答案 0 :(得分:3)

您的函数f1创建了一个新的局部变量a阴影全局变量a

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

该变量的范围为f1。它调用的任何函数都有自己的作用域,f1中的作用域不会对它调用的任何其他函数产生任何影响(除了闭包)。因此,当f2访问a时,它正在访问全局 a。否则,确定行为几乎是不可能的,因为它完全取决于调用上下文,调用上下文可以在对同一函数的不同调用之间变化。如果要将某个值传递给函数,请将其作为参数传递。

答案 1 :(得分:1)

在同一段中,它也说明了这一点:

  

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

因此答案应该是“GOG”。

答案 2 :(得分:1)

在功能中包含块是任何控制结构,例如, ifforswitch

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

f2不在f1块中。他们被宣布在同一水平。但是你可以在另一个函数中定义一个函数:

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
    }
}

答案 3 :(得分:0)

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

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

a := "O"中的f1仅更新f1的本地,并且不会影响全局变量。因此f2将从全局变量中读取a(值相同G)。

总结一下,在f2()中致电f1时,f2()位于f1的阻止中,但输入f2后,{{1}我的块与f1无关。

答案 4 :(得分:0)

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

package main

var a string

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

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

func f2() {
    print(a)
}

删除':'之前' ='你将引用全局变量