go: `:=` operator causes accidental shadowing
Go provides :=
operator to make declaring variables easier. It is a shorthand to declare and set a value of a variable. for example,
can be written as
But if not careful, this can accidently shadow variable bindings. Let’s look at the fictitious piece of code.
package main
import "fmt"
func fictitiousFunc() (int, error) {
return 42, nil
}
func main() {
x := 10;
x, err := fictitiousFunc()
if err != nil {
fmt.Println("I'll never print")
}
fmt.Println("value of x: ", x)
}
This produces following output
value of x: 42
While, this following piece of code will fail to compile
package main
import "fmt"
func fictitiousFunc() (int, error) {
return 42, nil
}
func main() {
x := 10
// replace :=
var x int
var err error
x, err = fictitiousFunc()
if err != nil {
fmt.Println("I'll never print")
}
fmt.Println("value of x: ", x)
}
output:
prog.go:12: x redeclared in this block
previous declaration at prog.go:10
So we can see that the operator is somewhat intelligent, and does not redeclare the variables.
Now what if we push it down a scope? See the following code
package main
import "fmt"
func fictitiousFunc() (int, error) {
return 42, nil
}
func main() {
someCondition := true
x := -1;
if someCondition {
x, err := fictitiousFunc()
if err != nil {
fmt.Println("I'll never print")
}
fmt.Println("value of x inside: ", x)
}
fmt.Println("value x outside: ", x)
}
This produces,
At line: 16, since the immediate scope (line:15-32) does not have variable x
declared, :=
is redeclaring the variable. a.k.a the variable x
gets shadowed.
Only workaround I can think of is not to use :=
, i.e change the code to
if someCondition {
var err error
x, err = fictitiousFunc()
if err != nil {
fmt.Println("I'll never print")
}
fmt.Println("value of x inside: ", x)
}
If you know something better let me know.