Golang tutorial - 6 Function
Tags: go, beginners, tutorial
Published: 2020-06-05 02:56:37

Writing a good code is a must in any programming language. Good code means the code runs effectively and efficiently. Also, good code must be readable so that code is easy to understand by many people, especially programmers or developers. Writing good code can be done by splitting a big part of code into smaller chunks of code by using a function.

## Function in Go
The function is a piece of code that performs specific tasks that can be reused. In the Go programming language. The anatomy of function declaration looks like this:

```go
//func receiver functionName(parameters types) return type
 func (receiver)funcName(params) returnValues {
    //code
}
```
To use the function, call the function name with arguments that are specified in the function.
```go
//declare a function called greet
func greet() {
    fmt.Println("Hello!")
}

func main() {
    greet() //prints "Hello!"
}

```
Based on the code above, we declare a simple function called `greet()` inside the main function. We use term parameters in function declaration whilst we use term arguments in function usage. Here is another example of function declaration.
```go
//With one parameter with return value type string
func greet(s string) string {
	return fmt.Sprint("Hello ", s, "!")
}

//With two parameters with return value type boolean
func search(word string, keyword string) bool {
	return strings.Contains(word, keyword)
}

//With variadic parameter with two return values type int
func countAvg(xi ...int) (int, int) {
	total := 0
	//calculate sum of ints
	for _, v := range xi {
		total += v
	}
	//calculate average of int
	avg := total / len(xi)

	return total, avg
}
```
These functions can be used inside the `main()` function.
```go
greetings := greet("John Doe")
sum, avg := countAvg(1, 2, 3, 4, 5, 6)
fmt.Println(greetings)
fmt.Println("sum: ", sum, " average: ", avg)
fmt.Println(search("Go is really awesome", "is"))
```
Output:
```
Hello John Doe!
sum:  21  average:  3
true
```
Based on the code above, there is a unique parameter called variadic parameters. The variadic parameter is a parameter that can be used by multiple values dynamically. The variadic parameter must be put in the last section of the parameter declaration inside the function in Go.
```go
//example
func foo(s string, xi ...int) {
    //code
}
//this is incorrect, throw an error
func foo(xi ...int, s string) {
    //code
}
```
## Function with receiver
When declaring a function in Go, the receiver in the function can be declared as well. This receiver is really useful if we working with `struct`. The receiver determines the entity that is capable of using a function.

Before writing a function, let's create a simple `struct` called `person`.
```go
type person struct {
    name string
}
```

Then, create a function called `greet()` with receiver type `struct` called `person`.
```go
func (p person) greet() {
	fmt.Println("Hello, my name is", p.name, "!")
}
```
To use this function, the struct must be instantiated first then call the function.
```go
func main() {
	p := person{name: "Firstname"} //instantiate the struct
	p.greet()                      //call greet() from instantiated struct called p
}
```
Output:
```
Hello, my name is Firstname !
```
## Anonymous Function
The anonymous function is a function without a name or identifier. The declaration of anonymous function in Go is like this:
```go
func() {
	//code
}
//using IIFE (Immediately-invoked Function Expression) style, we can declare a function that executes directly
func() {
    //code
}() //use this notation to execute the function 
```
The usage of the anonymous function can be seen in this example:
```go
func() {
    //calculates sum
    xi := []int{1,2,3,4,5,6}
    total := 0
    for _, v := range xi {
        total += v
    }
    fmt.Println("The sum is: ",total)
}()
```
Output:
```
The sum is:  21
```
## First Class Citizen in Go
The first-class citizen principle in Go is also available but rarely used. The first-class citizen means that a function can be used as an argument or parameter in a function. Here is an example.
```go
func main() {
	//declare a function that stored inside variable called cb
	cb := func(xi ...int) int {
		total := 0
		for _, v := range xi {
			total += v
		}
		return total
	}

	//declare a slice of int
	data := []int{1, 2, 3, 4, 5, 6}
	//call foo() function with arguments:
	//1. cb means callback function
	//2. data... means retrieve all items from slice called "data"
	result := foo(cb, data...)
	fmt.Println("the result: ", result)
}

func foo(callback func(...int) int, xi ...int) int {
	return callback(xi...)
}
```
Output:
```
the result:  21
```
## Closure
Closure means a function that can access variables from outside its body.
This is an example of closure.
```go
//declare a function that returns a function with return value int
func increment() func() int {
	i := 0 //forms a closure
	return func() int { 
		i++ //access variable "i" from outside this function body
		return i
	}
}

func main() {
	myInt := increment()
	fmt.Println(myInt())
	fmt.Println(myInt())
	fmt.Println(myInt())

	myInt2 := increment() //this function call resets "i" value
	fmt.Println(myInt2())
}
```
Output:
```
1
2
3
1
```

## Recursion
Recursion is a function that is capable of executing a function itself. Some problems can be solved using recursion like factorial calculation. Here is an example.
```go
func factorial(n int) int {
	if n == 0 || n == 1 {
		return 1
	} else {
		return n * factorial(n-1) 
	}
}

func main() {
	result := factorial(5)
	fmt.Println("The result: ", result)
}
```
Output:
```
The result:  120
```
Based on the code above, the recursion function works like this:

![How factorial works](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/udbq97xfq9khqe6epk4l.gif)

## defer, panic, and recover
There is a case when the function needs to be executed at a certain time for example `functionA()` has to be executed after a certain function is finished. Based on this case, the `defer` statement is useful. `defer` pushes a function into a list. The list of functions is executed after the surrounding function's execution is finished.

Here is the example:
```go
//(x,y int) is shorthand version of (x int, y int)
func calculate(x, y int) int {
	return x + y
}

func main() {
	defer fmt.Println("First")
	fmt.Println(calculate(4, 5))

}
```
Output:
```
9
First
```
Based on the code above, the deferred function `fmt.Println("First")` is executed after the `fmt.Println(calculate(4, 5))` returns or finished.

There are many error-handling mechanisms in Go, one example is using the `panic` function. If the error occurs, the `panic` is executed and the program is stopped.

An example of `panic` usage:
```go
func divide(x, y int) int {
	if y == 0 { //if the value of y equals 0, then the program panicking and stopped
		panic("cannot divide by 0")
	} else {
		return x / y
	}
}

func main() {
	fmt.Println(divide(24, 0))
	fmt.Println("Hello") //this isn't executed because the divide() is panicking
}
```
Output:
```
panic: cannot divide by 0
```
Based on the code above, the `panic` function stops the program if the condition matches (in this case, if the value of "y" equals 0). 

The deferred function is still executed although the program is panicking.
```go
func divide(x, y int) int {
	if y == 0 {
		panic("cannot divide by 0")
	} else {
		return x / y
	}
}

func main() {
	defer fmt.Println("Hello") //this is executed because this function is deferred
	fmt.Println(divide(24, 0))
}
```
Output:
```
Hello
panic: cannot divide by 0
```
To recover a program that is panicking, the `recover` function can be used in the deferred function. The `recover` function becomes useless if used in a non-deferred function because if the program is panicking, the deferred function is still executed.
Here it is the example:
```go
func divide(x, y int) int {
	if y == 0 {
		panic("cannot divide by 0")
	} else {
		return x / y
	}
}

func main() {
	//declare an anonymous func to recover from panic
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered!")
		}
	}()
	fmt.Println(divide(24, 0))
}
```
Output:
```
Recovered!
```
Based on the code above, the `divide()` function is panicking but the deferred function is still executed. The anonymous function is executed to recover from panicking then the program execution is stopped.

## Notes
Learn more about function in Go:
- [Function](https://go.dev/ref/spec#Function_types)
- [Function Declaration](https://go.dev/ref/spec#Function_declarations)
- [Function Literal](https://go.dev/ref/spec#Function_literals)
- [Closure](https://tour.golang.org/moretypes/25#:~:text=Go%20functions%20may%20be%20closures,%22bound%22%20to%20the%20variables.&text=Each%20closure%20is%20bound%20to%20its%20own%20sum%20variable.)
- [How recursion function works visually](https://visualgo.net/en/recursion)
- [defer, panic, and recover](https://go.dev/blog/defer-panic-and-recover)

I hope this article is helpful to learn the Go programming language. If you have any thoughts or feedback, you can write it in the discussion section below.