author
Kevin Kelche

A Guide to Scope and Lifetime of Variables in Golang


Introduction

A scope can be defined as where in a program a variable can be referenced. And Lifetime is for how long variables exist in the memory. Golang like other programming languages inhibits these attributes in its variables. In this article, we learn about scopes, lifetimes, and some memory allocation in Golang.

Scope

In Golang there are three types of scopes: Block scope, Package scope, and Global scope.

Block scope

Block-scoped variables are those variables that are declared within a given block, be it a function or conditionals like if statements, for loops, etc. These variables are only accessible within the given block and not outside of the block.

Let’s look at an example below.

main.go
package main

import "fmt"

func someFunc(){
 i := 20

    fmt.Printf("We have %d initialized.", i)
}

Copied!

In the above example, the someFunc function initializes variable i which can be accessed by the Printf function within the same function. If we were to access the variable i outside the function it would result in a compile error.

main.go
package main

import "fmt"

func someFunc(){
 i := 20

    fmt.Printf("We have %d initialized.", i)
}

func main() {
 someFunc()
    fmt.Printf("Trying to print %v .", i)
}

Copied!

If you try to run this program it will exit with an error that ./main.go:13:40: undefined: i

We’ll discuss later how we can access the value of i from the main function.

Package scope

Package-scoped variables are variables that are accessible in every part of the package. These variables are usually declared out of any blocks.

Let’s look at examples of package-scoped variables.

main.go
package main

import "fmt"
var(
 i = 100
)

func someFunc(){
    i+=200
    fmt.Println(i)
}

func main(){
 someFunc()
    fmt.Println(i)
}

Copied!

In this example, we declared a variable i and initialized it with the value of 100. The variable can be accessed by both the main function and the someFunc function. As you can see from the result is that when the someFunc increments the value, the value is incremented all accross the package.

output
go run main.go
300
300

Copied!

Here is an example of another file in the same package accessing the variable i.

anotherFile.go
package main

import "fmt"

func otherFunc(){
    fmt.Printf("I am accessing %v from anotherFile.go\n", i)
}

Copied!

main.go
func main(){
 someFunc()
    fmt.Println(i)
 otherFunc()
}

Copied!

From running this program you can see that you can access the variable i from within the package.

Note

Functions names are also variables, if declared outside of the block they are by default package scoped variables.

Global scope

Globally scoped variables are package variables that can span their reach out of the package. These functions can be termed exported variables. To export a variable in Golang you have to capitalize it. These variables can be accessed from any package that imports that package.

Let’s see an example of this.

Create a new directory called the store and create a new function called mystore.go then open and add this code.

Terminal
mkdir store && cd store && touch mystore.go && code .

Copied!

store/mystore.go
package store

import "fmt"
const (
 SomeVar = 30
)

func DataIsBeautiful() {
    fmt.Print("Data is beautifull.\n")
}

Copied!

Remember to run go mod init in your file to create a module.

Terminal
cd ..
go mod init scope-tut

Copied!

In your root folder add a main.go file and import it from the store package.

main.go
package main

import (
 "fmt"
 "scope-tut/store"
)

func main(){
    fmt.Printf("We are accessing someVar with value %v.\n", store.SomeVar)
    store.DataIsBeautiful()
}

Copied!

By running this program you’ll see that we can access the variables from the package store from the main package. If SomeVar or DataIsBeautiful were declared in lowercase it would have resulted in compile time errors.

Lifetimes

As mentioned earlier a Lifetime is when a variable exists in the memory. In Golang, the lifetime of a variable is determined by the scope of the variable. The lifetime of a variable is the same as the scope of the variable, meaning that if a variable is declared in a block, it will be destroyed when the block is exited. This is because a stack frame is created for each block and the variables are stored in the stack frame. When the block is exited, the stack frame is destroyed and the variables are destroyed with it.

main.go
package main

import "fmt"

func someFunc(){
 i := 10
    fmt.Printf("We have %d initialized.", i)
}
...

Copied!

main-stack-frame

On run funciton and exit

As you can see from the image a stack frame was assigned to someFunc function. When the function is exited the stack frame is destroyed and the variable i is destroyed with it.

When dealing with package-scoped variables the lifetime is the same as the lifetime of the program. This is because the variables are stored in a heap and are not destroyed when the function is exited. This is the same as when a function returns a pointer to a variable within that function.

main.go
package main

import "fmt"

func someFunc() *int{
 i := 10
 return &i
}

func main(){
 j := someFunc()
    fmt.Println(*j)
}

Copied!

In the above example, the variable i is stored in the stack frame of the function someFunc. When the function is exited the stack frame is destroyed and the variable i is destroyed with it. However, since the function returns a pointer to the variable i it will escape the stack frame and be stored in the heap until the program is exited.

heap-memory-allocation

heap memory allocation

Conclusion

To sum up, in this tutorial, we explored the variable scope in Golang. We learned that a variable’s scope is limited to the block in which it is declared, and its lifespan is equal to its scope. Additionally, package-scoped variables are accessible from any function within the package, whereas globally-scoped variables can be accessed by any package that imports the corresponding package.

Subscribe to my newsletter

Get the latest posts delivered right to your inbox.