Go closures
Dan Corin
February 15, 2017
Say we need a map to store various versions of a configuration in Go. Here is a simple example of the structure:
Given this config map, we need to create an additional map that uses the same strings as the keys, but has functions for values. The catch is that the body of each function needs to make use of the value from its corresponding key. For example, functions["prod"] should have a value of type func() string and the body of that function should make use of the value, envs["prod"]. Here's a concrete example:
Playground code here.
The intent of the above is to create a map[string]func() where functions["dev"] returns 1 and functions["prod"] returns 2. However, the above code prints the following when run:
It turns out, the variable value isn't bound to the function until after exiting the loop. Because of this, all funcs in functions return the value that value has during the last iteration of the loop. You can add a print statement to show that this is the case. Interestingly, adding a print statement also changes the order over which the map is iterated:
Output:
We confirm that both functions return the value that value has during the last iteration of the loop.
We can use a closure to get the behavior we want. That is, that each function returns the correct value from the initial map:
Playground code here.
Output:
Using the closure allows us to bind the loop variable to the function that we assign to the functions map, and we get our desired result.
Discussion in the ATmosphere