[tutorial tips-dan-trik]

How to Overcome Handling Errors in Golang

Currently, Santekno will discuss error handling in the Golang language. We will learn from easy handling to some very complex implementations. Golang already provides easy error handling, we can also make slight modifications so that the error can be more easily understood by ourselves and the people who will collaborate with us in the future. The first thing we will do is customize Golang’s default Error.

Golang provides a simple interface for handling Errors, every time there is an Error it will be returned by Golang following the definition of the interface.

type error interface{
  Error() string
}

Create Custom Golang Error

package main

import(
  "errors"
  "fmt"
)

func hitungArea(radius int)(int, error){
  if radius < 0 {
    return 0, errors.New("Tidak boleh kurang dari nol")
  }
  return radius * radius, nil
}

func main() {
  area, err := hitungArea(-1);
  if err != nil {
    fmt.Println("Terdapat kesalahan...")
    return
  } 
  
  fmt.Println(area)
}

In the code above, we will follow the scenario to calculate the area in a circle, we need to ensure that the radius cannot have a negative value or we can say less than zero. If the radius value sent is negative then the returned value will be “0” and an Error message has been defined.

In the calculateArea() function, if it is called in the main function it will return 2 values, namely, first the calculation value and second the Error object. To customize Error in the calculateArea() function you need to add a check, if the err object is not equal to nil then we will display error information that we can understand. Imagine if we have an Error that is not customized, sometimes we don’t know where the Error occurred.

There is a little trick from Santekno too, usually to do this customization we also need the Error information contained in the calculateArea() function as well because it could be that if we do this customization, we end up with an Error which we don’t actually know what the error means. like what, then in the main function we add the Error information in the following way:

func main() {
  area, err := hitungArea(-1);
  if err != nil {
    fmt.Printf("Terdapat kesalahan. Err: %s", err)
    return
  } 
  
  fmt.Println(area)
}

Get to know “Defer”

We will first discuss defer. See the code example below to make it easier to understand

package main

import "fmt"

func balikPesan() {
  fmt.Println("Ini contoh simple penggunaan fungsi Defer")  
}

func main() {
  defer balikPesan()
  fmt.Println("Ini baris pertama")
  fmt.Println("Ini baris kedua")
  fmt.Println("Ini baris ketiga")
}

In the code above we use defer to call the returnMessage() function which we save at the beginning before we print each line of information like the code above. What does the printed code above look like? Can anyone guess?

This is what it looks like when the code above is executed

result defer in golang

Even though it is called at the top of main(), the returnMessage() function is executed after the lines in the main() function have finished. Then the returnMessage() function is executed at the end of the function. And that’s how defer works in Golang.

Getting to Know “Panic”

Panic is usually used to stop programs with customized message information. When we call panic the instructions in the program will run as follows

  • Functions currently running will be terminated (stop)
  • Any function called with defer will be executed first
  • Program execution will stop

Here is a simple code for using panic

package main

import "fmt"

func jalankanPanic(){
  panic("Ini contoh pesan pada situasi Panic")
  fmt.Println("fungsi ini berjalan dengan selesai")
}

func main(){
  jalankanPanic()
  fmt.Println("fungsi main berjalan sampai selesai")
}

In the code above we call the panic function inside the executePanic() function. After the program is run, it will stop suddenly with terminate. It can be seen from the results of the program above like this

the result of panic in golang

The program exits on the 6th line when the panic function runs. The panic function is another way to notify the program that an error has occurred and instruct it to terminate with a custom error message.

Added “Defer” into “Panic” function

As explained, every time the panic function is executed the function that uses defer will be executed first until it is finished. Let’s look at the example program code below

package main

import "fmt"

func lakukanRecovery(){
  fmt.Println("Fungsi ini untuk melakukan recovery")
}

func jalankanPanic(){
  defer lakukanRecovery()
  panic("Ini contoh pesan pada situasi Panic")
  fmt.Println("fungsi ini berjalan dengan selesai")
}

func main(){
  jalankanPanic()
  fmt.Println("fungsi main berjalan sampai selesai")
}

What are the results of the program above after running it? Curious? According to the information mentioned above, the result is that the function under defer will be executed first, let’s see below

the result of panic in golang

On line 11, panic runs, then the defer function will be executed first before being stopped. Once panic occurs, it will look for all defer functions to run before stopping.

Using “Recovery”

Once a panic situation occurs, the program will stop. In fact, in the real world, applications that stop due to errors are not good. So a mechanism is needed to recover from these errors. We need to condition recovery to avoid unwanted application termination.

The defer function is always executed when the function is experiencing panic or no panic occurs. So we will create a recovery scenario in the defer function.

Detect panic situations

In the defer function we have to check whether the function execution experiences panic or not. To detect this, we will run the recover() function. After we run the function, we will get the same error message information as the parameter value passed to the panic function. The message will be returned as the output function of recover() and will not be allowed to terminate but will be controlled and the calling function will run normally. Let’s look directly at an example program

package main

import "fmt"

func lakukanRecovery() {
	if pesanRecover := recover(); pesanRecover != nil {
		fmt.Println(pesanRecover)
	}
	fmt.Println("Fungsi ini untuk melakukan recovery")
}

func jalankanPanic() {
	defer lakukanRecovery()
	panic("Ini contoh pesan pada situasi Panic")
	fmt.Println("fungsi ini berjalan dengan selesai")
}

func main() {
	jalankanPanic()
	fmt.Println("fungsi main berjalan sampai selesai")
}

After running the program above, the result is that the program will give a panic information message but the program continues to run until the end without the program stopping. It can be seen below

the result panic, defer recovery in golang

Conclusion

Error handling in Golang does look different compared to other languages. So we need to know several things that must be considered to handle this error. We also have to think about the mechanism for ‘recovery’ so that our program continues to run and doesn’t stop suddenly if an error occurs which results in a ‘panic’ situation.

comments powered by Disqus