DEV Community

Cover image for Variable Scope and Variable Shadowing in Golang
Abhinav Prajapati
Abhinav Prajapati

Posted on

Variable Scope and Variable Shadowing in Golang

Variable scope refers to the block or region of code in which a variable can be accessed. Go uses lexical scoping (also known as static scoping) based on blocks.

A block is a sequence of declarations and statements enclosed within matching curly braces {}.

Let's consider the following Go code:

package main

import "fmt"

func main() {
    var x int = 5

    if true {
        x := 15
        fmt.Println("Value of x at stage 1:", x)

        x = 20
        fmt.Println("Value of x at stage 2:", x)
    }

    fmt.Println("Value of x at stage 3:", x)
}
Enter fullscreen mode Exit fullscreen mode

What do you think the output of this code will be? Let's evaluate it.

The line x := 15 declares a new variable within the scope of the if block. So, whenever x is modified inside that block, the changes apply only to the inner x, not to the outer one.

Therefore, the output will be:

Value of x at stage 1: 15
Value of x at stage 2: 20
Value of x at stage 3: 5
Enter fullscreen mode Exit fullscreen mode

This behavior is called variable shadowing. It occurs when a variable declared in an inner scope has the same name as a variable declared in an outer scope.

When you write x := 15, you are not assigning a new value to the x whose value is 5. Instead, you are declaring a completely new and distinct variable that just happens to have the same name. Go allocates separate memory for this inner x.

From that point until the closing brace } of the if block, the inner x shadows (or hides) the outer x. Whenever the Go compiler encounters x inside that block, it resolves it to the variable in the innermost scope.

Here's what happens at each stage:

  • Stage 1: A new variable x is initialized with the value 15. The outer x (which is 5) still exists, but it is temporarily hidden.
  • Stage 2: The statement x = 20 updates the inner x. The outer x remains unchanged.
  • Stage 3: The if block ends, so the inner x goes out of scope. The name x now refers to the outer variable again, which still holds the value 5.

One simple way to avoid this issue is to choose variable names carefully so that shadowing doesn't happen unintentionally.

Variable shadowing is a common source of subtle bugs in Go, especially when working with multiple return values. A frequent example is accidentally shadowing the err variable inside loops or conditional blocks by using := instead of =.

Have you ever run into a bug caused by variable shadowing in Go? Share your experience in the comments!

Top comments (0)