This post is about declaration scopes and shadowing in Go.

package main import "fmt" func f(x int) { for x := 0; x < 10; x++ { fmt.Println(x) } } var x int func main() { var x = 200 f(x) }

This program declares x four times. All four are different variables because they exist in different scopes.

package main import "fmt" func f() { x := 200 fmt.Println("inside f: x =", x) } func main() { x := 100 fmt.Println("inside main: x =", x) f() fmt.Println("inside main: x =", x) }

In Go the scope of a declaration is bound to the closest pair of curly braces, { and } . In this example, we declare x to be 100 inside main, and 200 inside f .

What do you expect this program will print?

package main import "fmt" func main() { x := 100 for i := 0; i < 5; i++ { x := i fmt.Println(x) } fmt.Println(x) }

There are several scopes in a Go program; block scope, function scope, file scope, package scope, and universe scope. Each scope encompasses the previous. What you are seeing is called shadowing.

var x = 100 func main() { var x = 200 fmt.Println(x) }

Most developers are comfortable with a function scoped variable shadowing a package scoped variable.

func f() { var x = 99 if x > 90 { x := 60 fmt.Println(x) } }

But a block scoped variable shadowing a function scoped variable may be surprising.

The justification for a declaration in one scope shadowing another is consistency, prohibiting just block scoped declarations from shadowing another scope, would be inconsistent.