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?