Closures

2-minute read

A closure is a function that stores (“closes over”) an environment (a set of captured variables) and another function that uses that environment. We can create closures using anonymous functions.

Anonymous functions are functions without an identifier (a name). They are useful when we may want to associate a set of steps with arguments and/or return values without having to refer to or call the function more than once.

Here is an example of a closure:

package main

import "fmt"

func intSeq() func() int {
	i := 0
	return func() int {
		fmt.Printf("address of i: %p\n", &i)
		i++
		return i
	}
}

func main() {
	nextInt := intSeq()
	fmt.Println(nextInt())
	fmt.Println(nextInt())
	fmt.Println(nextInt())
	fmt.Println(nextInt())
	fmt.Println(nextInt())

	newInt := intSeq()
	fmt.Println(newInt())
	fmt.Println(newInt())
	fmt.Println(newInt())
	fmt.Println(newInt())
	fmt.Println(newInt())

}
closure.go
Copy

The function intSeq returns an anonymous function that increments a variable i. The function intSeq sets the value of the variable i to $0$ each time it is called. The memory addresses of i being printed for nextInt and newInt are different, lending to the idea that the i being referenced in the anonymous function returned in each call of intSeq is different.

The i initialized in each call of intSeq is the “environment” being enclosed by the function. Functions, such as the main function, calling intSeq are unable to access this environment but can interact with it via the anonymous function being returned by intSeq.

Support us via BuyMeACoffee