Go Closures will be explained in this post. First we’ll start of with an introduction: functions can contain functions. Then we’ll give an example of a closure and finally a practical app.

Closure

Nested functions

Go functions can contain functions. Those functions can literally be defined in functions.

The example below outputs “hello world”, but demonstrates this nested functions principle.


func main(){
    world := func() string {
        return "world"
    }
    fmt.Print("hello ", world(),"\n")
}

What is a closure?

In the next example, it creates a closure. The closure returns a number that increases each time its called.

You can use the variable x inside the increment function below. The function increment and variable x form the closure.


func main(){
    x := 2
    increment := func() int {
        x++
        return x
    }
    fmt.Println(increment())
    fmt.Println(increment())
    fmt.Println(increment())
}

x will keep being modified by the increment function. Each time the function increment() is called, x is modified.

{% pullquote %} A closure is a type of function, that uses variables defined outside of the function itself. {% endpullquote %}

Generator

You can use the idea of closures to make a number generator.

In the example below function makeSequence() returns an anonymous function that generates odd numbers. An anonymous function is just a function without a name.


func makeSequence() func() int {
    i:=1
    return func() int {
        i+=2
        return i
    }
}

makeSequence() returns a function, that function returns the numeric output.

Then we create a function: sequence generator:


sequenceGenerator := makeSequence()

And use it like this:


fmt.Println(sequenceGenerator())
fmt.Println(sequenceGenerator())

Full code:


package main

import "fmt"

func makeSequence() func() int {
   i:=1
   return func() int {
      i+=2
      return i
   }
}

func main(){
    sequenceGenerator := makeSequence()
    fmt.Println(sequenceGenerator())
    fmt.Println(sequenceGenerator())
    fmt.Println(sequenceGenerator())
}