Closures
In this page:
What Makes a Closure
A closure is simply a function literal that refers to a variable declared outside of it -- Go automatically keeps that variable alive and accessible to the function for as long as the closure itself exists.
Example: What Makes a Closure
package main
import "fmt"
func main() {
message := "hello"
greet := func() {
fmt.Println(message)
}
greet()
}
Login to try C/C++/Java/PHP code in the editor
Closures Share, Not Copy, Captured Variables
Because a closure captures the variable itself rather than a snapshot of its value, changes made inside the closure are visible outside it, and changes made outside are visible the next time the closure runs.
Example: Closures Share, Not Copy, Captured Variables
package main
import "fmt"
func main() {
count := 0
increment := func() {
count++
}
increment()
increment()
fmt.Println("count:", count)
}
Login to try C/C++/Java/PHP code in the editor
Building a Counter Factory
A classic use of closures is a function that returns another function, which keeps its own private state alive between calls -- like a counter generator that hands back an independent, incrementing counter each time it's called.
Note: Each call to makeCounter creates a brand-new, independent count variable.
Example: Building a Counter Factory
package main
import "fmt"
func makeCounter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
counter := makeCounter()
fmt.Println(counter())
fmt.Println(counter())
fmt.Println(counter())
}
Login to try C/C++/Java/PHP code in the editor
- Assuming each closure gets its own independent copy of a captured variable, when closures actually share a reference to the same variable.
- Creating closures in a loop pre-Go-1.22 and being surprised they all captured the same final loop variable value.
- Using a closure to mutate shared state from multiple goroutines without any synchronization, causing a data race.
- A closure is a function literal that references variables from outside its own body.
- Captured variables are shared by reference, not copied -- changes inside the closure are visible outside, and vice versa.
- Closures are commonly used to build function factories, like counters or accumulators.
- Since Go 1.22, each loop iteration gets a fresh variable, making closures inside loops behave intuitively.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: