← Back to Go Course | Chapter 4: Functions | Lesson 6 of 7

Closures

A closure is a function that packs its own little backpack of variables from where it was created, so it can still use them later even after it travels somewhere else.

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

markup
package main

import "fmt"

func main() {
	message := "hello"
	greet := func() {
		fmt.Println(message)
	}
	greet()
}

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

markup
package main

import "fmt"

func main() {
	count := 0
	increment := func() {
		count++
	}
	increment()
	increment()
	fmt.Println("count:", count)
}

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

markup
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())
}
Common Mistakes
  1. Assuming each closure gets its own independent copy of a captured variable, when closures actually share a reference to the same variable.
  2. Creating closures in a loop pre-Go-1.22 and being surprised they all captured the same final loop variable value.
  3. Using a closure to mutate shared state from multiple goroutines without any synchronization, causing a data race.
Chapter Summary
  • 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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.