
As Golang is not the first language programmers usually learn, I assume you already have good knowledge in at least one other programming language and now expanding your knowledge to Golang. If you are just trying to find the error handling mechanism on the official API docs by looking for the try/catch mechanism, you probably got tired of finding that and may be thinking Golang might don’t have any error handling mechanism at all!
Well, Golang doesn’t have support for try/catch, for sure. But, it also has its own unique approach to error handling, that no other language has adopted before. It does have a nice and easy-to-understand ‘errors’ package that helps you to deal with error objects, and to handle or create your own error object. For special exception errors, it uses its own unique ‘recover’ mechanism to handle them, which you might need to be using while dealing with sensitive situations like database connectivity, calculating complex mathematical operations that might end up with a divide by zero error, or test exception case in writing unit testing in Golang etc. You can also generate such a situation yourself with ‘panic’ as well. We will see them one by one briefly.
Error Handling In Method Call:
First, let’s start with how we would know and handle if one of our method invocations has generated some kind of error or not. In Golang, this approach is somewhat different from other programming languages. You will know why later in this article.
[In case you don’t know already: Golang methods can return multiple values at the same time!]
Let’s see a simple Golang code example snippet that will make it easier to understand better:
returnValue, err := myMethodCall();
if err != nil {
//do something
}
Code language: JavaScript (javascript)
In case of more than one valid return value, err should be returned as the last return value.
Golang Error Handling Object:
If you are writing a method yourself that requires returning errors if something wrong happens in between, use the ‘errors’ package for such a purpose. Let’s see a small example:
import (
"errors"
)
func myFunc(i int) (int, error) {
if i <= 0 {
return -1, errors.New("value should be greater than zero")
}
return i, nil
}
Code language: JavaScript (javascript)
As you can see, if any error occurs, the return value is null(or something similar, -1 in this case) and the error is set along with a helpful message. On the other hand, if no error occurs, the error is set to nil.
Panic/Recover Concept:
As I already mentioned earlier in this post, there is no try-catch; Golang uses the concept of “panic”/”recover” instead. We have already seen how we would handle the custom error, if occurs inside a method call and how to return a such error from methods that we write ourselves. However, these don’t deal with/can handle unexpected run-time errors that might occur.
Well, why Golang is using panic recover instead of try/catch, that’s certainly a different discussion. But, in easy words, let me ask you this: how frequently have you seen using try/catch in an existing fair-sized project? I believe you have seen a lot. So, here the term ‘exception’ isn’t really an exceptional case, is it? Also, if we need to return a custom error, we are taking the help of these exceptions as well. So, basically custom errors and runtime errors are all messed up together. Right?
Here, in Golang, we are dealing with these differently traditionally:
- Custom error handling has its own way, as we have seen earlier, by returning error instances besides other return values.
- Panic/recover mechanisms are expected to use in truly exceptional cases, and its control flow is different from try/catch in other languages.
Sure, I do recommend you to search on the internet a bit more to learn more details on ‘why’.
So basically, if something very odd/unique exception case has occurred, you will want to do a panic call that will stop the regular flow and causes the process to crash intentionally. And if such a case occurs from inside a function and you want to track such a situation, you will have to add a ‘recover’ mechanism as a deferred function.
Doing a Panic:
Creating a panic is far easier than its consequences/impact on the code 😉 . Here is a simple panic call:
anOddCondition := true
if anOddCondition {
panic("I am panicking")
}
Code language: JavaScript (javascript)
Recovering from a panic:
To add the ability to recover from a panic error, either add an anonymous function or define a custom function and call it with the ‘defer’ keyword from inside the method, where panic might occur from other internal calls. You don’t have to worry about where to place this method-specific order call, as it will always differ at the end of the current method’s statements execution completes.
If nothing wrong happens, this call will simply won’t have any impact at all. Otherwise, it will catch the error and you can do your custom handling with the error object(logging it etc). A simple recovery mechanism code example is given below:
func myMethod() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Error: ", err)
}
}()
//do whatever you want that might generate a panic error
}
Code language: JavaScript (javascript)
Final Words:
Golang team also describes the defer, panic and recover concept in depth in a blog post, which you can read through as well if you want. If something in this tutorial isn’t clear enough, please ask your question by commenting below. Happy coding 🙂
Leave a Reply