Functions are first citizens in go.
A function returning a function is a powerful idiom.
Closures take this on a higher level.
These concepts are orthogonal to concurrency.
Functions and closures are used a lot throughout this repo.
-
Closures are the Generics for Go by Jon Bodner "We could use
interface{}
as a way to pass untyped input and output parameters around but that misses the point. It creates ugly code that requires casts and subverts the type system that helps us write correct code."Shows clearly, that 'generics' can be attacked and solved using
- generated code - for generic algorithms & data structures
- closures - as shown here
- see below
type sorter struct { ... }
- see below - akadancing
in dlx
package main
import (
"fmt"
)
func outer2(name string) int {
var total int
myClosure := func(x int) {
total = len(name) * x
}
helper(myClosure)
return total
}
func helper(f func(int)) {
f(4)
}
func main() {
fmt.Println(outer2("hello"))
}
Result: 20
- = 5 * 4
- = _`(len("hello"))`_ * 4 )
- = _`(len("hello") * x )`_(4)
- = _`(len(name)`("hello")` * x )`_(4)
"Look at outer2
. Its local variable total
was modified when myClosure
was passed to helper
and called from there.
There’s no reference to total
in helper
, but using a closure allowed it to be modified.
Just like structs in Go, closures have state.
This state provides the solution to our problem."
package main
import (
"fmt"
"sort"
)
type sorter struct {
len int
swap func(i, j int)
less func(i, j int) bool
}
func (x sorter) Len() int { return x.len }
func (x sorter) Swap(i, j int) { x.swap(i, j) }
func (x sorter) Less(i, j int) bool { return x.less(i, j) }
func Sort(n int, swap func(i, j int), less func(i, j int) bool) {
sort.Sort(sorter{len: n, swap: swap, less: less})
}
func main() {
a := []int{5, 4, 3, 2, 1}
Sort(
len(a),
func(i, j int) {
temp := a[i]
a[i] = a[j]
a[j] = temp
},
func(i, j int) bool {
return a[i] < a[j]
})
fmt.Println(a)
b := []string{"bear", "cow", "ant", "chicken", "dog"}
Sort(
len(b),
func(i, j int) {
temp := b[i]
b[i] = b[j]
b[j] = temp
},
func(i, j int) bool {
return b[i] < b[j]
})
fmt.Println(b)
}