W3Basic Logo

Go Closures

Let's continue with advanced topics about functions. In Go, a closure is a special kind of function that can access variables from the surrounding scope.


The most common use case is to create generators, that is, functions that return a new value from a given sequence each time they are called.

Fibonacci generator

Let's start with a simple example. We want to create a function that returns the next Fibonacci number each time it is called.

func fibonacci_generator() func() int {
	a, b := 0, 1
	return func() int {
		a, b = b, a+b // update the variables in the surrounding scope
		return a
	}
}

To use this function, we need to call it first to get the generator function, and then call the generator function each time we want a new value:

package main

import "fmt"

func fibonacci_generator() func() int {
	a, b := 0, 1
	return func() int {
		a, b = b, a+b // update the variables in the surrounding scope
		return a
	}
}

func main() {
	fibgen := fibonacci_generator()
	for i := 0; i < 10; i++ {
		fmt.Println(fibgen())
	}

}

Output

1
1
2
3
5
8
13
21
34
55

Prime number generator

Our next example is a bit more complex. We want to create a function that returns the next prime number each time it is called.

We will start by defining the next_prime function, which returns the next prime that is greater than n:

func is_prime(n int) bool {
	for i := 2; i < n; i++ {
		if n%i == 0 {
			// n is divisible by i
			return false
		}
	}
	return true
}

func next_prime(n int) int {
	n++ // we don't want to return n if it is prime
	for !is_prime(n) {
		n++
	}
	return n
}

This function is not very efficient, but it is good enough for our purpose. Now, we can define a generator that will output a new prime number each time it is called:

func prime_generator() func() int {
	n := 2
	return func() int {
		n = next_prime(n) // update n in the surrounding scope
		return n
	}
}

And finally, a main function that prints the first 10 prime numbers may look like this:

func main() {
	// Print the first 10 prime numbers
	gen := prime_generator()
	for i := 0; i < 10; i++ {
		fmt.Println(gen())
	}
}

Let us stitch all the methods into a single program that prints the first 10 prime numbers.

package main

import "fmt"

func is_prime(n int) bool {
	for i := 2; i < n; i++ {
		if n%i == 0 {
			// n is divisible by i
			return false
		}
	}
	return true
}

func next_prime(n int) int {
	n++ // we don't want to return n if it is prime
	for !is_prime(n) {
		n++
	}
	return n
}
func prime_generator() func() int {
	n := 2
	return func() int {
		n = next_prime(n) // update n in the surrounding scope
		return n
	}
}

func main() {
	gen := prime_generator()
	for i := 0; i < 10; i++ {
		fmt.Println(gen())
	}

}

Output

3
5
7
11
13
17
19
23
29
31

This is a rather advanced example, but it is closer to real-world use cases than the previous one.

© 2023 W3Basic. All rights reserved.

Follow Us: