Go Closures
A closure is a function value that remembers variables from the place where it was made. The closure can read and change those variables after the outer function returns.
A counter factory keeps its own count
makeCounter returns a closure. The closure adds one to count on each call.
package main
import "fmt"
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
next := makeCounter()
fmt.Println(next())
fmt.Println(next())
fmt.Println(next())
}Two counters stay separate
Each factory call makes a new count. The two counters grow apart from each other.
package main
import "fmt"
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
first := makeCounter()
second := makeCounter()
fmt.Println(first())
fmt.Println(first())
fmt.Println(second())
}A closure changes a captured variable
The literal reads and changes total from the enclosing scope. Both calls change the same total.
package main
import "fmt"
func main() {
total := 10
addFive := func() {
total += 5
}
addFive()
addFive()
fmt.Println(total)
}Example
package main
import "fmt"
func makeGreeter(name string) func() {
count := 0
return func() {
count++
fmt.Println("Hello", name, count)
}
}
func main() {
greetHana := makeGreeter("Hana")
greetOmar := makeGreeter("Omar")
greetHana()
greetHana()
greetOmar()
}Key points
- A closure keeps access to variables from its enclosing scope.
- A function literal is function code written without a name.
- A factory function is a function that builds and returns a closure.
- Each call to a factory makes fresh variables for the new closure.
- A closure can change a captured variable.
- The change stays in place for the next call of the same closure.
- Two closures from one factory do not share their captured variables.
In this example, makeGreeter builds a closure for Hana and keeps a count for her. The first two calls print her greetings with counts 1 and 2. The Omar closure has its own count, so his first greeting prints 1.
Note
A captured variable stays alive for as long as its closure is in use.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Go Playground
Exercise
Why does a second counter from the same factory start again at 1?