W3Basic Logo

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.

© 2023 W3Basic. All rights reserved.

Follow Us: