Go - (8) Advanced Functions
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

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