Go Variable Scope
In Go, we can declare variables in two different scopes.
- Local Scope
- Global Scope
For Example:
package main
import "fmt"
// Global Variable
var text string
func main() {
text = "Hello"
// Local Variable
var message string = "Go Programming"
fmt.Printf("%s , %s", text, message)
}
Output
Hello , Go Programming
Based on the scope, we can classify the variables into
- Local Variables - Generally declared and accessed within the function code block
- Global Variables - Declared outside of all the function blocks and can be accessed by globally in a program
In our above example text
variable is global variable and message
variable is a local variable.
Let us explore about these concepts in details with examples.
When you define a variable inside a function, what does it become when the value is returned (or when the last instruction in the function is executed)? Let's find out.
package main
import "fmt"
func double(x int) int {
x = x * 2
return x
}
func main() {
fmt.Println(double(6))
fmt.Println(x)
}
The snippet above will not compile. The error message is the following:
./prog.go:12:14: undefined: x
But there is nothing specific to functions in this example. Let's try the same thing with a for
loop:
package main
import "fmt"
func main() {
for x := 0; x < 10; x++ {
fmt.Println(x)
}
fmt.Println(x)
}
We get the same error message. The variable x
is not accessible outside the for
loop.
What is common to the code inside functions and the code inside loops is that they are both surrounded by curly braces. This is called a block, and the rule is that variables defined inside a block are not accessible outside that block.
As a consequence, the following code is completely valid:
package main
import "fmt"
func main() {
{
const x = 0
fmt.Println(x)
}
{
const x = 1
fmt.Println(x)
}
}
You are not changing the value of the constant x
, you are just defining a new constant with the same name in a different block.
Shadowing
A consequence of the rule we have stated above is that you can define a variable with the same name as a variable defined in an outer scope. This is called shadowing.
package main
import "fmt"
func main() {
x := 0
fmt.Println(x)
{
x := 1
fmt.Println(x)
}
fmt.Println(x)
}
The output of this program is:
0
1
0
This is a very common pattern in Go, and it is used to avoid name collisions.
Global scope
The only place where you can define a variable without using curly braces is at the package level. This is called the global scope and variables defined here are accessible from anywhere else in the package.
package main
import "fmt"
var x = 0
func main() {
fmt.Println(x)
}
For now, you can think of a package as simply a file. We will see later how to split a package into multiple files.