Go handles first-class functions and closures in a pretty typical / standard way. For some good background on closures in general, see the Wikipedia article. In this case, calling adder
itself:
- Creates the
int
object named sum
with value 0
.
- Returns a closure: a function-like thingy1 that, when called, has access to the variable
sum
.
The particular function-like thingy that adder
returns, which its caller captures in an ordinary variable, is a function that takes one argument. You then call it, passing the one argument. There's nothing special about this argument-passing: it works the same way as it would anywhere else. Inside the function-like thingy, using the variable x
gets you the value that the caller passed. Using the name sum
gets you the captured int
object, whatever its value is. Returning from the function leaves the captured int
still captured, so a later call to the same function-like thingy sees the updated int
in sum
.
By calling adder
twice, you get two slightly-different function-like thingies: each one has its own private sum
. Both of these private sum
s are initially zero. Calling the function-like thingy whose value you've saved in pos
gets you the function that uses one of them. Calling the slightly-different function-like thingy whose value you've saved in neg
gets you the function that uses the other one.
1There's no real difference between this "function-like thingy" and an actual function except that this particular function-like thingy doesn't have a name by which you can invoke it. That's more or less what it means to have first-class functions.
If you're stuck on readability issues...
The original form of this is:
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
Let's rewrite this with a few type names and other syntactic changes that leave the core of the code the same. First, let's make a name that means func(int) int
:
type adderClosure func(int) int
Then we can use that to rewrite adder
s first line:
func adder() adderClosure {
...
}
Now let's make a local variable inside adder to hold the function we're going to return. To be explicit and redundant, we can use this type again:
var ret adderClosure // not good style: just for illustration
Let's now assign that variable to our closure by doing this:
sum := 0
ret = func(x int) int {
sum += x
return sum
}
and then we can return ret
to return the closure. Here's the complete code on the Go Playground.