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
函数中包含哪些块?
为什么另一个函数不包含块?
答案 0 :(得分:3)
您的函数f1
创建了一个新的局部变量a
,阴影全局变量a
:
func f1() {
a := "O"
print(a)
f2()
}
该变量的范围为f1
。它调用的任何函数都有自己的作用域,f1
中的作用域不会对它调用的任何其他函数产生任何影响(除了闭包)。因此,当f2
访问a
时,它正在访问全局 a
。否则,确定行为几乎是不可能的,因为它完全取决于调用上下文,调用上下文可以在对同一函数的不同调用之间变化。如果要将某个值传递给函数,请将其作为参数传递。
答案 1 :(得分:1)
在同一段中,它也说明了这一点:
块中声明的标识符可以在内部块中重新声明。 虽然内部声明的标识符在范围内,但它表示 内部声明声明的实体。
因此答案应该是“GOG”。
答案 2 :(得分:1)
在功能中包含块是任何控制结构,例如, if
,for
或switch
。
函数可以包含变量块。在您的示例中,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
调用f2
,f1
的返回地址时,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)
}
删除':'之前' ='你将引用全局变量