Higher Order Functions (HOF)
We can pass functions as data to another function.
A function that takes in another function as a parameter or returns another function is called a Higher-order function.
func aggregate(a, b, c int, arithmetic func(int, int) int) int {
return arithmetic(arithmetic(a, b), c)
}
The aggregate ()
function takes four parameters. As you can see, the last one is another function. And the aggregate ()
function calls the passed-in function twice and returns an int.
First Class Function (FCF)
- A function that is treated like another variable.
HOFs and FCFs are usually used as,
- HTTP API handlers
- pub/sub handlers
- onclick handlers
Currying
- Writing a function that takes function/s as parameters and returns a new function.
- It is not very commonly used in programming.
// Takes two integers and returns their product
func multiply(x, y int) int {
return x * y
}
func doMath(mathFunc func(int, int) int) func (int) int {
return func(x int) int {
return mathFunc(x, x)
}
}
func main() {
squareFunc := doMath(multiply) // Pass the multiply function to doMath
fmt.Print(squareFunc(5))
}
In the above example, square(5)
internally does doMath(multiply(5, 5))
. So the final answer is 25. Here we have wrapped multiply inside a new function that always multiplies a number by itself.
Defer
- A keyword unique to Go.
- Allow a function to execute automatically right before its enclosing function returns.
Why is this defer()
required? Check the example below. The copyFile
function has several return statements. When you open a file, you should close it once its usage is done. But you have done it before every return statement. This is tedious. So instead, you can use a defer
.
func copyFile(desination, source string) (written int64, err error) {
src, err := os.Open(source) // open file
if err != nil { return }
defer src.Close()
dest, err := os.Create(desination) // create file
if err != nil { return }
defer dest.Close()
return io.Copy(dest, src) // copy source file content to dest file
}
Closures
- Functions that reference variables that are outside their function bodies.
- They may also access and assign to the referenced variables.
// closure function
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
func main() {
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
fmt.Println(c()) // 3
d := counter() // new counter
fmt.Println(d()) // 1
}
In the above example, the count
variable in counter()
is outside of the function body of its return function. But whenever you call c
(in the main function) again and again, the reference to the count
is increased.
Anonymous functions
- Functions with no names
- used in closures or when you return a function as a return value.
Check the example below.
func main() {
// Anonymous function assigned to a variable
greet := func(name string) string {
return "Hello, " + name
}
// Call the anonymous function
message := greet("Edward Cullen")
fmt.Println(message)
}
The above example will print Hello, Edward Cullen