Deep Dive into Variable Scopes in Golang: Learn with Examples

Robin
Updated on July 5, 2023

The variable scope refers to the part of a program where a variable is visible and can be accessed. It defines the accessibility and visibility of a variable within the program.

The scope of a variable determines where you can reference it and how long it remains valid during program execution.

There are two common types of variable scopes in Golang:

  • Global Scope.
  • Local Scope.

These scopes are very helpful while writing and maintaining code. Because when you declare a variable globally, you are able to access it anywhere within your package.

Variables declared in a local scope are only accessible within a limit. You can't use them outside. Therefore, it becomes easy to understand and update later.

In this blog post, we will take a comprehensive journey into the world of variable scopes in Golang. Through real-world examples, we will explore the different types of scopes and learn how to use them effectively.

Global Scope in Golang

Global scope in Go refers to the variables declared at the package level. When you declare variables outside of any function, typically at the top of a Go file, they become global scope variables.

You can access and modify these variables from any part of the package, including other files within the same package. It is important to remember when you try to declare a global scope variable, you have to use the var keyword.

          package main

import "fmt"

// Global variable
var globalCount int

func main() {
    globalCount = 10 // Modifying the global variable
    fmt.Println(globalCount) // Accessing the global variable

    updateCount() // Function call to updateCount()
    fmt.Println(globalCount) // Accessing the updated global variable
}

func updateCount() {
    globalCount = 20 // Modifying the global variable within another function
}

        

In this example, we have a global variable named globalCount declared outside the main() function. You can read and modify it from both the main() function and the updateCount() function.

You can even use this variable from another file within the main package. Because this globalCount variable is globally available throughout the entire package.

In the main() function, we modify the value of globalCount to 10 and then print its value. Next, we call the updateCount() function, which further modifies the value of globalCount to 20. Finally, we print the updated value of globalCount from the main() function.

However, excessive use of global variables is not a good idea as it can lead to potential issues. If you use such variables too much and change their values in different places, it will be very hard to catch errors and update the program in the future.

Also Read: Golang Variable: Different Ways to Create Variables in Golang


Local Scope in Golang

When we talk about local scope in Go, think of it as a more restricted area where variables are accessible only within a specific function or block of code. Local variables are like private resources that are limited to a particular part of your program.

Local variables are typically temporary and have a limited lifespan, existing only as long as the function or block is being executed.

We can divide the local scope into two levels in Golang:

  • Function Level.
  • Block Level.

To understand the local scope, let's consider a real-world scenario. Imagine you're a cashier at a supermarket, and you have a function that calculates the total amount for a customer's purchase.

Within that function, you might have variables like subTotal, tax, and total, which are specific to that calculation.

          package main

import "fmt"

func calculateTotal(subTotal float64) float64 {
    tax := subTotal * 0.1 // Local variable specific to calculateTotal()
    total := subTotal + tax // Local variable specific to calculateTotal()
    return total
}

func main() {
    subTotal := 100.0 // Local variable within main()
    grandTotal := calculateTotal(subTotal) // Function call to calculateTotal()
    fmt.Println("Grand Total:", grandTotal)
}
        

In this example, we have a function called calculateTotal() that takes a subTotal as an argument and calculates the total by adding a 10% tax to it.

Both tax and total are local variables within the calculateTotal() function. They are created when the function is called and exist only within this function.

In the main() function, we declare another local variable subTotal, representing the customer's subtotal. We then call the calculateTotal() function, passing the subTotal value as an argument.

The calculateTotal() function performs its calculations using its local variables and returns the total.

Local variables are beneficial because they keep data isolated and prevent. Here you can't access the tax variable inside the main() function because this variable is local to the calculateTotal() function.

Both main() and calculateTotal() functions have subTotal variables. As these variables are declared in two separate functions, they will work independently. One won't affect another.

Also Read: Mastering Constant in Golang: Declare and Use It Like a Pro


Function Level

Variables declared within a function have function scope. They are only accessible within the function in which they are declared.

When you create a variable inside a function, that variable is only visible within that function. If you try to use it outside, Golang will throw an error.

          package main

import "fmt"

func main() {
    var functionLevel int
    functionLevel = 10
    fmt.Println(functionLevel)
}
        

Here I have functionLevel variable inside the main() function. This is a local variable in this function. That's why it is called function-level scope.

If you try to use this functionLevel variable in another function, you will get an error.

Also Read: Functions VS Methods in Golang: Understanding the Differences


Block Level

Variables declared within a block, such as an if statement, loop, or any pair of curly braces, have block scope. They are visible only within that specific block and any nested blocks within it.

Once the block execution is completed, the variables declared within it go out of scope and cannot be accessed anymore.

          package main

import "fmt"

func main() {
	if true {
		var blockVariable int
		blockVariable = 10

		fmt.Println(blockVariable)

		if true {
			nestedVariable := "Hello, world!"

			fmt.Println(blockVariable)
			fmt.Println(nestedVariable)
		}

		// nestedVariable is not accessible here
	}

	// blockVariable is not accessible here
	// nestedVariable is not accessible here
}
        

Here, I have blockVariable inside a if statement. There is a nested if statement where I have declared nestedVariable variable.

Inside the first if statement you can only access blockVariable but inside the nested if statement you can access both blockVariable and nestedVariable variables.

Outside these if statements you can't access any of these variables. Because they are block-level local variables.

You can also declare multiple variables with the same name in different block. Golang will execute them separately within their blocks.

          package main

import "fmt"

func main() {
	if true {
		var blockVariable int
		blockVariable = 10

		if true {
			blockVariable := "Hello, world!"

			fmt.Println(blockVariable)
			// Hello, world!
		}

		fmt.Println(blockVariable)
		// 10
	}

	// blockVariable is not accessible here
}

        

Here I have 2 if statements. Both of them have blockVariable variables. Even though these variables have the same names, they are declared in different blocks.

Therefore, when you run the program, they will be executed separately. They will also show different results because they are storing different types of values.

Also Read: Understanding All Data Types in Golang: A Complete Guide


Global Scope VS Local Scope

Both global and local scopes help determine the accessibility of variables in a Golang application. But there are some differences between them.

These are the most important differences between global and local scopes in Golang:

Global ScopeLocal Scope
VisibilityVisible throughout the entire programLimited to the specific block or function
AccessAccessible from any part of the programAccessible only within the block or function
PriorityThe lifetime of the programGolang gives more priority to a local variable than a global variable if they have the same names.
LifetimeLifetime of the programLimited to the execution of the block or function
Memory ManagementOccupies memory for the entire programOccupies memory only during execution
Name ClashesHigher risk of name clashesLower risk of name clashes
ModularityDecreases modularity if overusedPromotes code modularity and encapsulation

These differences will help you to choose between these scopes. You can declare your variables accordingly based on the requirements.

Also Read: Type Aliases in Golang: Create Custom Names For Your Types


Conclusion

Understanding the variable scopes is crucial to write Golang code, as they determine the visibility, accessibility, and lifetime of variables.

By appropriately utilizing different scopes, we can avoid naming conflicts, promote modularity, and manage memory efficiently.

That's why in this lesson, I have discussed everything you need to know about scoping in Golang for writing clean, organized, and efficient code.

We explored the different types of variable scopes in Go, including global and local scopes. You have seen function and block-level local scope as well.

When you have a clear understanding of these various scopes in Golang for your variables, it will become very easy to maintain your application and avoid unexpected errors.

Related Posts