Table of contents
Golang supports anonymous functions which are then used to form closure functions. Anonymous functions are functions without any name. Before going any further read about the anonymous function.
The closure is a special type of function value which references a variable declared outside its body. The purpose of this function is to close over a variable of the upper function to form a closure. The function may access and assign to the referenced variables; in this sense, the function is "bound" to the variables.
Let's see an example. In this example, we create a closure which keeps track of the page hit or as a counter.
package main
import "fmt"
func main() {
hit := 0
counter := func() int {
hit += 1
return hit
}
fmt.Println(counter())
fmt.Println(counter())
fmt.Println(counter())
}
Run this code in Go Playground
In the above example, we bound the closure to the hit
variable which is not passed to it but accessed as a global variable.
The problem with the above code is, hit
is a global variable. Hence another function has access to it. So any other operation can change the value of hit
. To avoid this closure can isolate the data.
package main
import "fmt"
func main() {
counter := Counter()
fmt.Println(counter())
fmt.Println(counter())
fmt.Println(counter())
}
func Counter() func() int {
hit := 0
return func() int {
hit++
return hit
}
}
Run this code in Go Playground
In the above example, closure is bound to or references to the hit
variable which is still can be accessed after the function call. This means closure has access to the data and no other function has access to it hence this data can be tracked and isolated. This is one of the benefits of closure.
Some closure use cases
Isolating the data
Suppose we want to create a function that persists data after the functional call exists. For example, we create a Fibonacci series generator where we want to keep all variables away from the user's eye, so no one can manipulate it.
package main
import "fmt"
func fibonacci() func() int {
n1 := 0
n2 := 1
return func() int {
n1, n2 = n2, (n1 + n2)
return n1
}
}
func main() {
f := fibonacci()
fmt.Println(0)
for i := 0; i < 10; i++ {
fmt.Println(f())
}
}
Run this code in Go Playground
Search in sorting package
A common use of Search is to find the index i for a value x in a sorted, indexable data structure such as an array or slice. In this case, the argument f, typically a closure, captures the value to be searched for, and how the data structure is indexed and ordered.
func Search(n int, f func(int) bool) int
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int{1, 3, 6, 8, 10, 15, 21, 28, 36, 45, 55}
x := 8
i := sort.Search(len(nums), func(i int) bool {
return nums[i] >= x
})
fmt.Printf("Index of %d is %d", x, i)
}
Run this code in Go Playground
Thank you for reading this blog, and please give your feedback in the comment section below.