Warning for accidental variable shadowing with block scope

Yesterday I ran into this problem in my code, and it cost me hours of debugging time. I showed my code to a go veteran and he didn’t recognize the problem right away either. This is mostly a case of a bug which is nearly invisible, rather than the language making wrong code look wrong.

I accidentally used a := instead of = in an assignment within a loop. The compiler interpreted it as if I had wanted to create a new variable in the loop scope with the same name as a variable in the outer function scope. This isn’t wrong according to the language, but it was definitely not what I wanted.

Here is an example illustrating what I did:

package main

import (
	"fmt"
)

func main() {

	counter := 0

	fmt.Println("Hello, playground")
	for i := 0; i < 5; i++ {
		fmt.Println("Loop Start -- counter from parent scope is visible")
		fmt.Println(counter)
		fmt.Println("Shadowing counter in next line with := rather than =")
		counter := counter + 1
		fmt.Println(counter)
		fmt.Println("next iteration -- local counter instance out of scope")
	}
	fmt.Println("Hello, playground")
}

https://play.golang.org/p/ndyFd5WamD

Why does go allow a variable to shadow another variable in the same function, even if they are in different block scopes?

I would like to see this become an error. It’s easy to do by accident and hard to catch. Some languages allow variables in a function to shadow globals, without allowing a variable to shadow other variables in the same function. You can do the exact same logic, but you have to use a different name.

I can’t think of a reason that this should not be considered an error. Does anyone have a use-case where shadowing in a loop block inside the same function is what you need?

You should be running ineffassign - https://github.com/gordonklaus/ineffassign - along with vet, lint, etc., as part of your check-in.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.