-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
Problem
The := syntax is error-prone when dealing with multiple targets and variables of enclosing scope:
// often a mistake:
var a int
{
a, b := foo() // creates a new 'a' in this scope instead of using 'a' of outer scope
}
// the fix
var a int
{
var b *Bar
a, b = foo()
}Not only is the fix verbose, it defeats a nicety of inferred typing that it often spares us from having to remember precise return type(s), e.g. whether a returned type is a pointer or not:
a := bar() // whether bar() returns an *X or just an X, we often don't need to care
Normally, Go disallows redeclarations, but it makes an exception for the := syntax, such that we can't look at an := assignment and know for sure which of the target variables are being declared:
x, y, z := foo() // only one of x, y, and z must be new, but just looking here doesn't tell us which variables are new
Another problem is that we can't mix 'name' targets and 'non-name' targets:
a, b[0] := foo() // compile error: b[0] is a non-name targetProposal
A syntax that marks individual targets of assignment as new variables. Let's say for now we'll use ' as a suffix marker:
x', y, z' = foo() // assign to new variable 'x', existing variable 'y', and new variable 'z'
We wouldn't remove the existing := syntax, of course, but in time its use would be considered non-standard style.
With this marking syntax, I don't see a good reason to disallow mixing in non-name targets:
a', b[0] = foo() // ok
It would also be nice if we could optionally specify types of one or more of the newly declared target variables to make them different from the corresponding return type:
a' Fruit, b = bar() // first return type of bar() is Banana, but we store it in a Fruit interface variableAs a last little bonus, perhaps type casts could be allowed on assignment targets:
a' int64(), b' = foo() // the int64() indicates a cast of the return value assigned to 'a'
//spares us from having to create an additional variable of the type we don't want:
notA', b' = foo()
a' = int64(notA)I think these syntax choices are compatible with the existing grammar, but regardless, I'm not strongly attached to this exact syntax.