In go, is there a sound use case for having multiple variables of the same name in the same scope?

Issue

The following (contrived) code defines two occurrences or "instances" of the variable i :

import "fmt"

func main() {
    goto_done := false
    i := 3
fred:
    fmt.Printf("i #1 = %d\n", i)
    if !goto_done {
        i := 4
        fmt.Printf("i #2 = %d\n", i)
        goto_done = true
        goto fred
    }
}

and from the output, as follows, it can be seen that these both persist as separate values, in that defining the second does not overwrite the first:

i #1 = 3
i #2 = 4
i #1 = 3

I can see the potential benefits (and potential pitfalls!) of using a variable of the same name as one in an outer scope, thus "hiding" the latter. But it seems absurd to allow a variable of the same name as another in the same scope to be defined and used without warning or complaint while leaving previous instance(s) intact!

So I wondered if this was an intentional feature, useful in certain situations. Or is it just an incidental result, a fairly harmless and rarely encountered "corner case", of the way variables work in go.

Solution

Shadowing allows you to copy and paste "self contained" code like this, and have it work (pretty much) wherever you put it.

// Print Fibonacci numbers
for i, j := 0, 1; j < 100; i, j = j, i+j {
    fmt.Println(j)
}

i and j are very common variable names so if shadowing wasn’t allowed, there’s a good chance of conflict if you try to paste this somewhere in your code, resulting in an error.

Of course, it’s generally good to avoid shadowing as it can lead to unexpected bugs and makes your code less readable (especially without scope-aware highlighting you might get in an IDE). In a longer, more realistic scenario, you would want to rename any shadowed names you might have pasted in. Thankfully, with shadowing being valid in the language, it should actually make it easier to rename them:

Since i and j are valid and distinct variables, a good IDE should allow you to quickly rename those variables and all their usages as you would any other variable.


Note: The inclusion of shadowing in the language is still a trade-off which could be argued for or against, but given that it is included, I think this counts as a sound use case.

Answered By – Hymns For Disco

Answer Checked By – David Goodson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.