go lang

what are filter, closure, and custom functions in go?

In this tutorial we are demonstrating some advance features of functions in go such filters, closures and custom functions.

Custom Functions:

Functions are the first class citizen in go. Using higher order function we can pass function as argument and return as output parameter from function too, also you can create type as a function and pass that as field in struct. The custom function is nothing but creating reusable function signature using type keyword.

package main

import "fmt"

// define function
type display func(string) string

// create function which will display message on console
func greetMessage(name string) string {

    return fmt.Sprintf("Hello %s", name)
}

func goodMorningGreet(name string) string {

    return fmt.Sprintf("Good morning %s", name)
}

func goodEveningGreet(name string) string {

    return fmt.Sprintf("Good evening %s", name)
}


func main() {
    var f display // define variable of type display

    f = greetMessage
	fmt.Println(f("Maheshwar"))
	
	f = goodMorningGreet
	fmt.Println(f("Maheshwar"))

	f = goodEveningGreet
	fmt.Println(f("Maheshwar"))
}

Output:

$ go run functiontype.go 
Hello Maheshwar
Good morning Maheshwar
Good evening Maheshwar

In the above code, we defined display custom function using type keyword, and with similar signature, we created greetMessage() function which takes a string as input and string as output and in main() function defined variable of type display and used that to calling our greetMessage() function.


 var f display // define variable of type display

    f = greetMessage
	fmt.Println(f("Maheshwar"))
	
	f = goodMorningGreet
	fmt.Println(f("Maheshwar"))

	f = goodEveningGreet
	fmt.Println(f("Maheshwar"))

This is the beauty of custom function or creating custom type of a function in go.

Filter functions in go:

Filter functions are functions that you can use to filter out the data, it is like a gatekeeper to allow certain data and certainly not. Let us take an example to understand more.

Example:

Let us filter out permanent employee and the employee part of IT department.

package main

import "fmt"

type Employee struct {
    name       string
    department string
    isPermanent    bool
}

func main() {

    e1 := Employee{"Maheshwar", "it", false}
    e2 := Employee{"Ram", "hr", true}
    e3 := Employee{"Sham", "operation", true}
    e4 := Employee{"Govind", "it", false}
    e5 := Employee{"Sri", "admin", true}

    emps := []Employee{e1, e2, e3, e4, e5}

    permanent := filter(emps, func(e Employee) bool {
        if e.isPermanent == true {
            return true
        }
        return false
    })

    itwale := filter(emps, func(e Employee) bool {

        if e.department == "it" {
            return true
        }
        return false
    })

    fmt.Println("permanent:")
    fmt.Printf("%v\n", permanent)

    fmt.Println("ITians:")
    fmt.Printf("%v\n", itwale)

}

func filter(s []Employee, f func(Employee) bool) []Employee {
    var res []Employee

    for _, v := range s {

        if f(v) == true {
            res = append(res, v)
        }
    }
    return res
}

Output:

$ go run filters.go 
permanent:
[{Ram hr true} {Sham operation true} {Sri admin true}]
ITians:
[{Maheshwar it false} {Govind it false}]

In this filter(emps, func(e Employee) bool. Filters take a list of employees and anonymous functions to filter out the data and return true or false based on the comparison.

func filter(s []Employee, f func(Employee) bool) []Employee {
    var res []Employee

    for _, v := range s {

        if f(v) == true {
            res = append(res, v)
        }
    }
    return res
}

This is the filter function it takes anonymous function as a argument and while calling used below snippet.

permanent := filter(emps, func(e Employee) bool {
        if e.isPermanent == true {
            return true
        }
        return false
    })

Closure in GO:

closure is a special type of anonymous function. Go supports anonymous functions, which can form closures. Anonymous functions are useful when you want to define a function inline without having to name it. Go functions may be closures. closure is a function value that references variables from outside its body.

package main

import "fmt"

func nextEven() func() int {

    i := 0
    return func() int {
        i+=2
        return i
    }
}

func main() {

    nextInt := nextEven()

    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())
	
	// this is the new calling new state
    nextInt2 := nextEven()
	fmt.Println("new state :: ",nextInt2())
	
	fmt.Println(nextInt())
}

Output:

$ go run closure.go 
2
4
6
8
new state ::  2
10

We have a method which is generating even numbers. It returns the closure which generates the next even number. This nextEven() function returns a function that returns a integer even number. The anonymous function accessing the ” i ” variable from outside.

func nextEven() func() int {

    i := 0
    // inline anonymous function which accessing i from outside
    return func() int {
        i+=2
        return i // return number
    }
}

Conclusion:

We learned closure which is very powerful function which is accessing variable from outside along with the custom type of a function and filter function to filter collection of data. I hope this is helpful to you.

Source Code:

https://github.com/maheshwarLigade/spring-boot-examples
$ git clone https://github.com/maheshwarLigade/GoLanguage-tutorials
$ cd GoLanguage-tutorials
$ go run closure.go