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,
var x int
= 42 x
can be written as
:= 42 x
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() {
:= 10;
x , err := fictitiousFunc()
xif err != nil {
.Println("I'll never print")
fmt}
.Println("value of x: ", x)
fmt}
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() {
:= 10
x // replace :=
var x int
var err error
, err = fictitiousFunc()
xif err != nil {
.Println("I'll never print")
fmt}
.Println("value of x: ", x)
fmt}
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() {
:= true
someCondition
:= -1;
x
if someCondition {
, err := fictitiousFunc()
x
if err != nil {
.Println("I'll never print")
fmt}
.Println("value of x inside: ", x)
fmt}
.Println("value x outside: ", x)
fmt
}
This produces,
: 42
value of x inside: -1 value x outside
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
, err = fictitiousFunc()
x
if err != nil {
.Println("I'll never print")
fmt}
.Println("value of x inside: ", x)
fmt}
If you know something better let me know.