It is best illustrated with the following Go code snippet.
var x int
x, y := 1, 2 // x declared above is set to 1, y is declared and set to 2
if true {
x, z := 3, 4 // declare a local x and z, and set them to 3 and 4. This x shadows the x declared above.
}
The trap is that the x in the if blocks is a new local variable that shadows the x variable declared in the enclosing block.
-
While constraining, the use of
:=
should not allow predefied variables in the lefthand side of:=
. This would remove any ambiguity. Unfortunately, this is not backward compatible and might break a lot of code. It is however my preferred solution because it removes all ambiguity on variable declaration and shadowing. It would be a short hand ofvar x, y = 1, 2
. -
A compiler warning should be issued when a variable on the lefthand side of
:=
might shadow a variable defined in the enclosing context. It would be backward compatible. But a lot of existing code would issue compiilation warnings. -
Dissalow the
:=
notation. I had to suggest it for completeness, but this would break even more code and piss off a lot of people. Don't even think of it. ;)
It is best illustrated with the following Go code snippet.
var x
x, y := 1, 2 // ok
var a struct{b int}
a.b, c := 1, 2 // compilation error: "expected identifier on left side of :=" or "non-name a.b on left side of :="
This appears inconsistent. Why is x
allowed and not a.b
? Both are predefined variables.
Even the compilation error message appears inconsistent. With the above code, the compilation error message is "expected identifier on left side of :=". If we remove the var x
and x, y := 1, 2
lines, the compilation error message becomes "non-name a.b on left side of :=".
-
Disallow use of any predefined variables on the lefthand side of
:=
. Any varible on the lefthand side of:=
would be declared at that spot. It's my preferred solution. See comment above. -
Allow use of
a.b
as any other predefined variables. There is no risk of shadow variable trap with this change. It would be backward compatible.
Note: published in "Golang experience report"
I encounter this issue quite a lot, especially when affecting values to members of structs.
var err error a.b, err = myFunc()
I think the first line is excessive.
Same goes when checking if a value is in an array, and affecting it to a member.
var ok bool a.b, ok = myMap[key]
I would happily use a new operator,
?=
that will first try to affect a value to a variable, if it exists, and then create a variable with that value.a.b, ok ?= myMap[key]