package main
var a string
func main() {
a = "G"
print(a)
f1()
}
func f1() {
a := "O"
print(a)
f2()
}
func f2() {
print(a)
}
I think f2
will be in f1
's block when call f2
in f1
, so the output will be GOO
, but the output is GOG
instead.
The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block. -- From https://golang.org/ref/spec#Declarations_and_scope
What are containing blocks inside a function?
Why another function is not containing block?
Your function f1
creates a new, local variable a
which shadows the global variable a
:
func f1() {
a := "O"
print(a)
f2()
}
That variable is scoped to f1
. Any function it calls has its own scope, no scope change within f1
has any impact on any other function it calls (excepting closures). So, when f2
accesses a
, it is accessing the global a
. Otherwise, determining behavior would be nearly impossible because it would depend entirely on the calling context which can vary between different calls to the same function. If you want to pass some value to a function, pass it as a parameter.
In the same paragraph it also says this:
An identifier declared in a block may be redeclared in an inner block. While the identifier of the inner declaration is in scope, it denotes the entity declared by the inner declaration.
Thus the answer should be "GOG".
Containing blocks in function are any control structures, like e.g. if
, for
or switch
.
Functions can be containing blocks for variables. In your example f1
is a containing block, as it redeclares a
and shadows the global declaration.
f2
is not in f1
s block. They are declared at the same level. But you could define a function inside another function:
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
}
}
To understand this question, I think you should first realize What happens when a function is called.
When f1
call f2
, f1
's return address, f2
's parameters and locals will be added to the stack. So f2
can only visit its locals and current globals.
The a := "O"
in f1
only updates the locals of f1
and doesn't affect the globals. So f2
will read a
(the value is same G
) from globals.
In summarize, when call f2()
in f1
, the f2()
is in f1
's block, but when enter f2
, f1
's block has no concern with f2
.
you are creating a new variable 'a' in f1() try this :
package main
var a string
func main() {
a = "G"
print(a)
f1()
}
func f1() {
a = "O"
print(a)
f2()
}
func f2() {
print(a)
}
by removing ':' before '=' you will refer to the global variable