Closures in Go¶
A Simple Closure¶
Informally, a closure is an object that refers to both a function and an environment of variables that the function can access.
For example, consider makeAdder1:
func makeAdder1(n int) func(int) int {
    f := func(a int) int {
        return n + a // n refers to the n passed-in to makeAdder1
    }
    return f // n escapes from makeAdder1
}
func test1() {
    add1 := makeAdder1(1)
    fmt.Println(add1(add1(3)))
}
It takes an int n as input and returns a new function f with
signature func(int) int, such that f(a) returns n + a. The
function f is a closure because f refers to a variable (namely n)
that was not defined inside f.
A Closure for Generating Fibonacci Numbers¶
The Fibonacci numbers are the sequence 1, 1, 2, 3, 5, 8, 13, …. The first two numbers are 1 and 1, and then every number after those equals the sum of the two numbers before, e.g. 13 = 5 + 8.
Here’s a nice function that returns a closure that, when called, returns the next Fibonacci number:
// genFib() returns a function that, every time it is called,
// returns the next Fibonacci number
func genFib() func() int {
    a, b := 0, 1
    return func() int {
        a, b = b, a+b
        return a
    }
}
func test() {
    nextFib := genFib()
    //
    // prints the first 10 Fibonacci numbers
    //
    for i := 0; i < 10; i++ {
        fmt.Printf("nextFib() = %v\n", nextFib())
    }
}
A More Sophisticated Closure¶
In this next example, the function makeAdder2 returns two closures that
share the same environment:
func makeAdder2() (func() int, func() int) {
    i := 0
    add := func() int {
        i++ // i is the i local to makeAdder2 defined above
        return i
    }
    get := func() int {
        return i // i is not local to get
    }
    return add, get // i escapes from makeAdder2
}
func test2() {
    incr, get := makeAdder2()
    fmt.Println(get())
    incr()
    incr()
    fmt.Println(get())
}
makeAdder2 returns two closures: the first adds 1 to the closed-over
variable i, and the second returns the current value of i.
The tricky part here is that the two returned closures refer to the variable
i that is local in makeAdder2. If i were stored on the call stack
(like regular local variables), then when makeAdder2 ends i would no
longer exist — causing add/get to not work!
So for these two closures to work correctly, i needs to be stored in a
location that is still accessible after makeAdder2 is done. Go
automatically determines when a variable like i “escapes” from a function,
and can thus ensure that i is stored in an accessible location.
Notice that the add and get closures share the same i variable.
They thus operate on the same underlying variable, which makes them similar to
methods in object-oriented programming.
Questions¶
- In your own words, describe what a closure is. Try to be as clear and precise as possible. 
- What does it mean when we say that a variable escapes from a function? 
- How does Go handle closures that refer to variables that have been defined outside of the closure? 
- Make a function called - genMult(n int)that returns a closure- f()such that every time- f()is called it returns- n, and after that ever time it’s called it returns a value that is- nmore than the previous value.- For example: - f := genMult(5) fmt.Println(f()) // returns 5 fmt.Println(f()) // returns 10 fmt.Println(f()) // returns 15 
- Modify - makeAdder2to return one more closure called- reset()that, when called, sets the value of the closed-over variable- ito 0. Test it to make sure it works correctly.