Friday, June 22, 2018

A Gotcha in Variable Initialisation in Golang

I'm new to Golang development, and there are lots of things I consider weird with the language. I've just discovered this gotcha, luckily before any code went live, so I figured I'd post about it.

Variables of the same name can be declared at multiple scopes within the same function, and as functions can return tuples, it's possible that, when declaring and initialising variables at the same time, you intend to actually reuse a previously declared variable.

For example:

  x := 1
  y := true
  if y {
    z, x := DoSomethingThatChangesX(x)
    fmt.Printf("Output: %d, %d", x, z)
  }

  fmt.Printf("If x is 1, oops: %d", x) // x == 1


The output of this will show that the x that is set as an output of DoSomethingThatChangesX will not be the same x as in the outer scope.

This next version shows how the code can be changed, in quite an ugly way, to avoid the gotcha:

  x := 1
  y := true
  if y {
    var z int
    z, x = DoSomethingThatChangesX(x)
    fmt.Printf("Output: %d, %d", x, z)
  }

  fmt.Printf("If x is 1, oops: %d", x) // x != 1


By separately declaring z before initialisation, z and x can both be assigned a value separately to declaration.

I know this will come across as pretty simplistic, and is obvious when you think about it, but I still think it would be really easy to increase some subtle bugs, which even careful eyes might not spot, because of it.