How to deal with Go lack of static local variables

May 21, 2019

  • do not use a global variable 💀

While static local variables are safe from external corruption, global variables almost encourage it!

package main

import "fmt"

var tot int // <- don't!
func counter(x int) int {
   tot += x
   return tot
}

func main() {
   nums := []int{1, 2, 5, 10, 3, 4}
   for _, v := range nums {
      counter(v)
   }
   fmt.Println("counter: ", counter(0))
}

@playground

Closures to rescue

  • in Go each function value created during execution is capable of being a closure over this scope
package main 

import "fmt"

func MakeCounter() func(int) int {
   var tot int
   return func(x int) int {
      tot += x
      return tot
   }
}

func main() {
   nums := []int {1, 2, 5, 10, 3, 4}
   counter := MakeCounter()
   for _, v := range nums {
      counter(v)
   }
   fmt.Println("counter: ", counter(0))
}

@playground

In this example MakeCounter() defines a local variable tot. Each time it’s invoked it creates both a new instance in memory of that variable and a new instance of an anonymous function which references that instance of tot because it closes over the state known to that instance of MakeCounter().

Like the previous example about the global variable tot isn’t passed to the function as a parameter, but instead it were available when the function was declared

As a regular function can reference global variables, using a closure we aren’t directly passing these variables to the function, but the function has access to them when it is called.