Anonymous Functions and Closures in Golang with Examples

Published on March 19, 2023

Golang allows functions to be assigned to variables, passed as argument to other functions and returned from other functions. Functions are first class citizens in Golang.

Anonymous functions

Anonymous function or function literal is a function without name. Anonymous functions useful for implementing functionality for short term use. See an example below:

// Create function literal - declare anonymous function
// and assign it to variable.
greeting := func() {
	fmt.Println("Hello, world!")
}
// Call this function.
greeting()

Will output Hello, world!. Note that greeting is variable here.

Closures

Function literal has access to variables defined in enclosing function. These variables live as long as they are accessible. Function literals are closures in golang.

func NewCounterFunction() func() {
	count := 0
	return func() {
		count++
		fmt.Println(count)
	}
}

func main() {
	counter := NewCounterFunction()

	counter() // 1
	counter() // 2

	counter2 := NewCounterFunction()
	counter2() // 1
}

Function NewCounterFunction declares variable count, creates and returns anonymous function as a result. This function has access to count variable, it will increment and prints current value of count, every time when you call it. Inside the main function we create function literal counter, call it two time and see call sequence number. Also, we create second counter counter2, it starts output from 1, because it refers to new instance of counter. These two anonymous function work independent and does not share variables between.

Example 1. Find element in a slice

Following example will show usage of Find function from sort package for seeking element in a slice.

Syntax:

func Find(n int, cmp func(int) int) (i int, found bool)

Find function accepts two arguments:

  • n int - max index in seeking slice
  • cmp func(int) int - comparator, anonymous function.
package main

import (
  "fmt"
  "sort"
)

func main() {
	// slice should be sorted!
	elements := []int{1, 2, 3, 4, 5}
	needle := 4

	idx, found := sort.Find(len(elements), func(i int) int {
		if needle < elements[i] {
			return -1
		}
		if needle > elements[i] {
			return 1
		}
		return 0
	})

	fmt.Println(idx, found) // 3 true
}

Anonymous function declared within main function and has access to elements and needle variables. Inline function passing can be replaced with passing function literal, as shown below.

comparatorFn := func(i int) int {
  if needle < elements[i] {
    return -1
  }
  if needle > elements[i] {
    return 1
  }
  return 0
}

idx, found := sort.Find(len(elements), comparatorFn)

Checkout how closures help implement functional options pattern →