Thursday 1 June 2017

Golang gotcha #3: Accidentally shadowed variables




A common mistake that I have often seen cause exasperation to many programmers is that of accidental variable shadowing, this is one of the first things that I look for when asked to help debug misbehaving code. This occurs via misuse of the short variable declaration clause :=.

Let's recap declaration, assignment and what the shorthand does:

So the := clause is shorthand for a declaration and an assignment, where the type of the declaration is implicitly inferred from the assignment value. It is very useful and the lack of verbosity feels almost like you are using a dynamic language.

Now when does this get us into trouble? The problem occurs when we accidentally declare and assign to a new variable in a different scope rather than assign to an existing variable in an outer scope.

'Short cuts make long delays' - Frodo Baggins

https://play.golang.org/p/Pset590PA2

This example demonstrates an accidental variable shadowing bug in code used to determine the highest integer in a slice. The variable 'highest' is redeclared and assigned to in the scope of the if statement, shadowing the 'highest' variable declared in the scope of main. Whereas desired behaviour is assignment to the highest variable declared in the scope of the main function. Here we say that the variable highest is 'shadowed' as a result of this redeclaration. Try modifying line 14 of the code to 'highest = v' and note the change in behaviour.

Now, it is a good question as to why this is allowed, I believe that it is primarily to allow flexibility and to protect existing code from things like imports as explained here.

This is catchable by using go vet with the experimental option -shadow enabled.

Note that it is necessary to invoke vet via 'go tool vet' rather than 'go vet' in order to enable flags, see this issue.

For those interested, more in depth discussion can be seen here.

No comments:

Post a Comment