In this article, we shall be discussing how to return and handle errors effectively using custom and inbuilt Golang functions, with help of practical examples.
Golang return error
An error is basically a fault that occurs in a program execution flow.
These errors can be of various natures:- Caused by programmers through
code syntax and interface errors, system-related
Resources and Runtime errors, algorithm-related
logic and arithmetic errors. Which later are solved through debugging
process.
In Golang ,The Error is an interface that holds Error() string
method. Its implemented as follows
type error interface {
Error() string
}
In an nutshell, when the Error() method is called, it’s return value
is in form of string datatype. Through the use of inbuilt Go functions
of the fmt and errors packages, we can construct the kind of error
message to be displayed. Below is an example to construct Errors using
fmt.Error() in Golang, i.e you want to read a file from a given path,
unfortunate the file doesn’t exist or the path given is invalid. For
example:=
package main
import (
"fmt"
"os"
)
func ReadFile(file string) error {
dataFile, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("An error occurred while Reading the file: open : %v", err)
}
fmt.Println(string(dataFile))
return nil
}
func main() {
resultsErr := ReadFile("")
if resultsErr != nil {
fmt.Printf("%v", resultsErr)
}
}
Output:
With the file attached ensure you replace the ReadFile(“test.txt”)
$ go run main.go
Hello
without file attached
$ go run main.go
An error occurred while Reading the file: open: no such file or directory
Explanation:- In the above code, ReadFile() error{} function
returns an error which is nil whenever no error encountered. In
Golang, the Error return value is nil as the default, or “zero”. Notice
that checking if err != nil{} is the idiomatic way to determine if
an error was encountered in Golang syntax, in this function we are
returning the error only, handling the file data within the function.
fmt.Error() enables us to customize the kind of message to be
displayed. These messages are always in a lowercase format and don’t end
with punctuation.
In Golang there are numerous ways to return and handle errors Namely:=
- Casting Errors
- Error wrapping mechanism
- Panic, defer and recover
Different methods of error handling in Go Func
Method 1:- Casting Errors
Casting errors is a way of defining custom and expected errors, with golang we can make use of erros.Isand errors.As() error functions to cast different types of errors. i.e,errors.Is we create a custom error of a particular type and check If the error matches the specific type the function will return true, if not it will return false.
package main
import (
"errors"
"fmt"
"io/fs"
"os"
)
var fileNotFound = errors.New("The file doesn't exist")
func ReadFile(file string) error {
dataFile, readErr := os.ReadFile(file)
if readErr != nil {
if errors.Is(readErr, fs.ErrNotExist) {
return fmt.Errorf("this fileName %s doesn't exist ", file)
} else {
return fmt.Errorf("Error occured while opening the file : %w", readErr)
}
}
fmt.Println(string(dataFile))
return nil
}
func main() {
fileName := os.Args[1]
if fileName != "" {
resultsError := ReadFile(fileName)
if resultsError != nil {
fmt.Printf("%v", resultsError)
}
} else {
fmt.Println("the file name cant be empty")
}
}
Output:
$ go run main.go "new"
this fileName new doesn't exist
Explanation:- We are using errors.Is(readErr, fs.ErrNotExist) {} to check if the file passed exist, if it doesn’t exist we return custom message as shown above. we can also use the custom error message such as errors.New() to create expected error and handle it as errors.Is(readErr, fileNotFound) {} the return values will be the same.
Method 2:- Error wrapping
Wrapping is a way of using other errors within a function to provide more context and detailed error messages.
fmt.Error() function enable us to create a wrapped errors with use of
%w flag. The %w flag is used for inspecting and unwrapping
errors.
In this subtitles we can incorporate other functions from errors
package used to handle errors, namely:-
errors.As, errors.Is, errors.Unwrap functions. errors.As is used to
cast a specific error type, i.e
func As(err error, target any) bool{}, also, the errors.Unwrap is
used to inspect and expose the underlying errors in a program,i.e
func (e *PathError)Unwrap()error{ return e.Err}, Furthermore the
errors.Is mostly for comparing error value against the sentinel value
if is true or false, i.e func Is(err,target error) bool{}.
Example of Error Wrapping
package main
import (
"errors"
"fmt"
"os"
)
func ReadFile(file string) error {
dataFile, readErr := os.ReadFile(file)
var pathError *os.PathError
if readErr != nil {
if errors.As(readErr, &pathError) {
return fmt.Errorf("this fileName %s doesn't exist and failed opening file at this path %v", file, pathError.Path)
}
return fmt.Errorf("Error occured while opening the file : %w", readErr)
}
fmt.Println(string(dataFile))
return nil
}
func main() {
fileName := os.Args[1]
if fileName != "" {
resultsError := ReadFile(fileName)
if resultsError != nil {
fmt.Printf("%v", resultsError)
}
} else {
fmt.Println("the file name can't be empty")
}
}
Output:
With the file attached ensure you replace the ReadFile(“test.txt”)
$ go run main.go
Hello
without file attached
$ go run main.go ""
the file name can't be empty
$ go run main.go next.txt
this fileName news.txt doesn't exist and failed opening file at this path news.txt
Explanation:- In the above code we have used fmt.Errorf() functions to format the error message to be displayed and wrapping error using a custom error message with wrap function errors.Is() which checks if the path exists. You can avoid unnecessary error wrapping and handle it once.
Method-3: Using Panic, Defer and Recover
We have covered this topic in detail in a separate articleGolang panic handing [capture, defer, recover, log]
Summary
At this point in this article, you have learned various ways to return and handle errors in the Golang function. In Go, Errors are considered to be a very lightweight piece of data that implements the Error interface. Custom errors in Go help in debugging and signaling where the error has occurred from. Error tracing is easy as compared to other programming languages. Golang application development, error handling is very critical and helps one not only during debugging but also to monitor the application behavior. We recommend you to read more about panic, recover and defer mechanism of error handling as well.

![Golang return error and handle [Best Practices]](/golang-return-error/golang_return_error.jpg)
