Go func return error

Handling errors is an essential feature of solid code. In this section, you'll add a bit of code to return an error from the greetings module, then handle it in the caller.

Handling errors is an essential feature of solid code. In this section, you’ll
add a bit of code to return an error from the greetings module, then handle it
in the caller.

  1. In greetings/greetings.go, add the code highlighted below.

    There’s no sense sending a greeting back if you don’t know who to greet.
    Return an error to the caller if the name is empty. Copy the following
    code into greetings.go and save the file.

    package greetings
    
    import (
        "errors"
        "fmt"
    )
    
    // Hello returns a greeting for the named person.
    func Hello(name string) (string, error) {
        // If no name was given, return an error with a message.
        if name == "" {
            return "", errors.New("empty name")
        }
    
        // If a name was received, return a value that embeds the name
        // in a greeting message.
        message := fmt.Sprintf("Hi, %v. Welcome!", name)
        return message, nil
    }
    

    In this code, you:

    • Change the function so that it returns two values: a
      string and an error. Your caller will check
      the second value to see if an error occurred. (Any Go function can
      return multiple values. For more, see
      Effective Go.)
    • Import the Go standard library errors package so you can
      use its
      errors.New function.
    • Add an if statement to check for an invalid request (an
      empty string where the name should be) and return an error if the
      request is invalid. The errors.New function returns an
      error with your message inside.
    • Add nil (meaning no error) as a second value in the
      successful return. That way, the caller can see that the function
      succeeded.
  2. In your hello/hello.go file, handle the error now returned by the
    Hello function, along with the non-error value.

    Paste the following code into hello.go.

    package main
    
    import (
        "fmt"
        "log"
    
        "example.com/greetings"
    )
    
    func main() {
        // Set properties of the predefined Logger, including
        // the log entry prefix and a flag to disable printing
        // the time, source file, and line number.
        log.SetPrefix("greetings: ")
        log.SetFlags(0)
    
        // Request a greeting message.
        message, err := greetings.Hello("")
        // If an error was returned, print it to the console and
        // exit the program.
        if err != nil {
            log.Fatal(err)
        }
    
        // If no error was returned, print the returned message
        // to the console.
        fmt.Println(message)
    }
    

    In this code, you:

    • Configure the
      log package to
      print the command name («greetings: «) at the start of its log messages,
      without a time stamp or source file information.
    • Assign both of the Hello return values, including the
      error, to variables.
    • Change the Hello argument from Gladys’s name to an empty
      string, so you can try out your error-handling code.
    • Look for a non-nil error value. There’s no sense continuing
      in this case.
    • Use the functions in the standard library’s log package to
      output error information. If you get an error, you use the
      log package’s
      Fatal function
      to print the error and stop the program.
  3. At the command line in the hello directory, run hello.go to
    confirm that the code works.

    Now that you’re passing in an empty name, you’ll get an error.

    $ go run .
    greetings: empty name
    exit status 1
    

That’s common error handling in Go: Return an error as a value so the caller
can check for it.

Next, you’ll use a Go slice to return a randomly-selected greeting.

< Call your code from another module
Return a random greeting >

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:

ALSO READ: Golang check if key exists in map [SOLVED]

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.

ALSO READ: Golang Print Struct Variables [SOLVED]

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.

ALSO READ: Golang SQLite3 Tutorial [With Examples]

Method-3: Using Panic, Defer and Recover

We have covered this topic in detail in a separate article Golang 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.

References

error-handling in Go
Working with errors in golang
Errors

Errors are a language-agnostic part that helps to write code in such a way that no unexpected thing happens. When something occurs which is not supported by any means then an error occurs. Errors help to write clean code that increases the maintainability of the program.

What is an error?

An error is a well developed abstract concept which occurs when an exception happens. That is whenever something unexpected happens an error is thrown. Errors are common in every language which basically means it is a concept in the realm of programming.

Why do we need Error?

Errors are a part of any program. An error tells if something unexpected happens. Errors also help maintain code stability and maintainability. Without errors, the programs we use today will be extremely buggy due to a lack of testing.

Golang has support for errors in a really simple way. Go functions returns errors as a second return value. That is the standard way of implementing and using errors in Go. That means the error can be checked immediately before proceeding to the next steps.

Simple Error Methods

There are multiple methods for creating errors. Here we will discuss the simple ones that can be created without much effort.

1. Using the New function

Golang errors package has a function called New() which can be used to create errors easily. Below it is in action.

package main

import (
	"fmt"
	"errors"
)

func e(v int) (int, error) {
	if v == 0 {
		return 0, errors.New("Zero cannot be used")
	} else {
		return 2*v, nil
	}
}

func main() {
	v, err := e(0)
	
	if err != nil {
		fmt.Println(err, v)      // Zero cannot be used 0
	}	
}

2. Using the Errorf function

The fmt package has an Errorf() method that allows formatted errors as shown below.

fmt.Errorf("Error: Zero not allowed! %v", v)    // Error: Zero not allowed! 0

Checking for an Error

To check for an error we simply get the second value of the function and then check the value with the nil. Since the zero value of an error is nil. So, we check if an error is a nil. If it is then no error has occurred and all other cases the error has occurred.

package main

import (
	"fmt"
	"errors"
)

func e(v int) (int, error) {
	return 42, errors.New("42 is unexpected!")
}

func main() {
	_, err := e(0)
	
	if err != nil {   // check error here
		fmt.Println(err)      // 42 is unexpected!
	}	
}

Panic and recover

Panic occurs when an unexpected wrong thing happens. It stops the function execution. Recover is the opposite of it. It allows us to recover the execution from stopping. Below shown code illustrates the concept.

package main

import (
	"fmt"
)

func f(s string) {
	panic(s)      // throws panic
}

func main() {
        // defer makes the function run at the end
	defer func() {      // recovers panic
		if e := recover(); e != nil {
            		fmt.Println("Recovered from panic")
        	}
	}()
	
	f("Panic occurs!!!") // throws panic 
	
	// output:
	// Recovered from panic
}

Creating custom errors

As we have seen earlier the function errors.New() and fmt.Errorf() both can be used to create new errors. But there is another way we can do that. And that is implementing the error interface.

type CustomError struct {
	data string
}

func (e *CustomError) Error() string {
	return fmt.Sprintf("Error occured due to... %s", e.data)
}

Returning error alongside values

Returning errors are pretty easy in Go. Go supports multiple return values. So we can return any value and error both at the same time and then check the error. Here is a way to do that.

import (
	"fmt"
	"errors"
)

func returnError() (int, error) {  // declare return type here
	return 42, errors.New("Error occured!")  // return it here
}

func main() {
	v, e := returnError()
	if e != nil {
		fmt.Println(e, v)  // Error occured! 42
	}
}

Ignoring errors in Golang

Go has the skip (-) operator which allows skipping returned errors at all. Simply using the skip operator helps here.

package main

import (
	"fmt"
	"errors"
)

func returnError() (int, error) {  // declare return type here
	return 42, errors.New("Error occured!")  // return it here
}

func main() {
	v, _ := returnError()   // skip error with skip operator
	
	fmt.Println(v)    // 42
}

Errors are a core part of almost every programming language, and how we handle them is a critical part of software development. One of the things that I really enjoy about programming in Go is the implementation of errors and how they are treated: Effective without having unnecessary complexity. This blog post will dive into what errors are and how they can be wrapped (and unwrapped).

What are errors?

Let’s start from the beginning. It’s common to see an error getting returned and handled from a function:

1
2
3
func myFunction() error {
    // ...
}

But what exactly is an error? It is one of the simplest interfaces defined in Go (source code reference):

1
2
3
type error interface {
	Error() string
}

It has a single function Error that takes no parameters and returns a string. That’s it! That’s all there is to implementing the error interface. We’ll see later on how we can implement error to create our own custom error types.

Creating errors

Most of the time you’ll rely on creating errors through one of two ways:

1
fmt.Errorf("error doing something")

Or:

1
errors.New("error doing something")

The former is used when you want to use formatting with the typical fmt verbs. If you aren’t wrapping an error (more on this below) then fmt.Errorf effectively makes a call to errors.New (source code reference). So if you’re not wrapping an error or using any additional formatting then it’s a personal preference.

What do these non-wrapped errors look like? Breaking into the debugger we can analyze them:

1
2
3
(dlv) p err1
error(*errors.errorString) *{
        s: "error doing something",}

The concrete type is *errors.errorString. Let’s take a look at this Go struct in the errors package (source code reference):

1
2
3
4
5
6
7
type errorString struct {
	s string
}

func (e *errorString) Error() string {
	return e.s
}

errorString is a simple implementation having a single string field and because this implements the error interface it defines the Error function, which just returns the struct’s string.

Creating custom error types

What if we want to create custom errors with certain pieces of information? Now that we understand what an error actually is (by implementing the error interface) we can define our own:

1
2
3
4
5
6
7
8
type myCustomError struct {
    errorMessage    string
    someRandomValue int
}

func (e *myCustomError) Error() string {
    return fmt.Sprintf("Message: %s - Random value: %d", e.errorMessage, e.someRandomValue)
}

And we can use them just like any other error in Go:

1
2
3
4
5
6
7
8
9
10
11
func someFunction() error {
    return &myCustomError{
        errorMessage:    "hello world",
        someRandomValue: 13,
    }
}

func main() {
    err := someFunction()
    fmt.Printf("%v", err)
}

The output of running this code is expected:

1
Message: hello world - Random value: 13

Error wrapping

In Go it is common to return errors and then keep bubbling that up until it is handled properly (exiting, logging, etc.). Consider this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
func doAnotherThing() error {
    return errors.New("error doing another thing")
}

func doSomething() error {
    err := doAnotherThing()
    return fmt.Errorf("error doing something: %v", err)
}

func main() {
    err := doSomething()
    fmt.Println(err)
}

main makes a call to doSomething, which calls doAnotherThing and takes its error.

Note: It’s common to have error handling with if err != nil ... but I wanted to keep this example as small as possible.

Typically you want to preserve the context of your inner errors (in this case “error doing another thing”) so you might try to do a superficial wrap with fmt.Errorf and the %v verb. In fact, the output seems reasonable:

1
error doing something: error doing another thing

But outside of wrapping the error messages, we’ve lost the inner errors themselves effectively. If we were to analyze err in main, we’d see this:

1
2
3
(dlv) p err
error(*errors.errorString) *{
        s: "error doing something: error doing another thing",}

Most of the time that is typically fine. A superficially wrapper error is ok for logging and troubleshooting. But what happens if you need to programmatically test for a particular error or treat an error as a custom one? With the above approach, that is extremely complicated and error-prone.

The solution to that challenge is by wrapping your errors. To wrap your errors you would use fmt.Errorf with the %w verb. Let’s modify the single line of code in the above example:

1
return fmt.Errorf("error doing something: %w", err)

Now let’s inspect the returned error in main:

1
2
3
4
5
(dlv) p err
error(*fmt.wrapError) *{
        msg: "error doing something: error doing another thing",
        err: error(*errors.errorString) *{
                s: "error doing another thing",},}

We’re no longer getting the type *errors.errorString. Now we have the type *fmt.wrapError. Let’s take a look at how Go defines wrapError (source code reference):

1
2
3
4
5
6
7
8
9
10
11
12
type wrapError struct {
	msg string
	err error
}

func (e *wrapError) Error() string {
	return e.msg
}

func (e *wrapError) Unwrap() error {
	return e.err
}

This adds a couple of new things:

  1. err field with the type error (this will be the inner/wrapped error)
  2. Unwrap method that gives us access to the inner/wrapped error

This extra wiring gives us a lot of powerful capabilities when dealing with wrapped errors.

Error equality

One of the scenarios that error wrapping unlocks is a really elegant way to test if an error or any inner/wrapped errors are a particular error. We can do that with the errors.Is function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var errAnotherThing = errors.New("error doing another thing")

func doAnotherThing() error {
    return errAnotherThing
}

func doSomething() error {
    err := doAnotherThing()
    return fmt.Errorf("error doing something: %w", err)
}

func main() {
    err := doSomething()

    if errors.Is(err, errAnotherThing) {
        fmt.Println("Found error!")
    }

    fmt.Println(err)
}

I changed the code of doAnotherThing to return a particular error (errAnotherThing). Even though this error gets wrapped in doSomething, we’re still able to concisely test if the returned error is or wraps errAnotherThing with errors.Is.

errors.Is essentially just loops through the different layers of the error and unwraps, testing to see if it is equal to the target error (source code reference).

Specific error handling

Another scenario is if you have a particular type of error that you want to handle, even if it is wrapped. Using a variation of an earlier example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type myCustomError struct {
    errorMessage    string
    someRandomValue int
}

func (e *myCustomError) Error() string {
    return fmt.Sprintf("Message: %s - Random value: %d", e.errorMessage, e.someRandomValue)
}

func doAnotherThing() error {
    return &myCustomError{
        errorMessage:    "hello world",
        someRandomValue: 13,
    }
}

func doSomething() error {
    err := doAnotherThing()
    return fmt.Errorf("error doing something: %w", err)
}

func main() {
    err := doSomething()

    var customError *myCustomError
    if errors.As(err, &customError) {
        fmt.Printf("Custom error random value: %dn", customError.someRandomValue)
    }

    fmt.Println(err)
}

This allows us to handle err in main if it (or any wrapped errors) have a concrete type of *myCustomError. The output of running this code:

1
2
Custom error random value: 13
error doing something: Message: hello world - Random value: 13

Summary

Understanding how errors and error wrapping in Go can go a really long way in implementing them in the best possible way. Using them “the Go way” can lead to code that is easier to maintain and troubleshoot. Enjoy!

Error handling is a mechanism added to many modern programming languages which typically defines how the code is going to react under unexpected circumstances. Some syntactic and semantic errors are directly dealt with by the compiler, who reports them as they are detected by the static checker. But there are some that need special handling. Many languages use specialized syntax to deal with errors that are a bit complex in their syntactical structure. Go is more simplistic and uses values to denote the type of error returned from functions like any other value. The article introduces the error handling mechanism of Go with some examples.

If you are unfamiliar with working with functions, you may want to read our article on the subject: Understanding Functions in Go.

Go Error Handling using the errors.New Functions

There is a package called errors in the Go standard library which implements functions to manipulate errors. The errors.New is a built-in function to create an error and specify a custom error message that can be shown to the user if such an error occurs. This function takes a single argument string which typically is the message we want to display and alarm the user regarding the error.

Let’s write a simple program that checks the validity of an email address and presents a built-in error message due to an invalid email address using Go:

package main

import (
	"fmt"
	"net/mail"
)

func isMailAddressValid(email string) (string, bool) {
	addr, err := mail.ParseAddress(email)
	if err != nil {
		return err.Error(), false		
	}
	return addr.Address, true
}

func main() {
	em, ok := isMailAddressValid("mymail**gmail.com")
	if ok {
		fmt.Println(em)
	} else {
		fmt.Println(em)
	}
}

If you run this code in your integrated development environment (IDE) or code editor, you get the following output:

mail: missing '@' or angle-addr

The above example simply displays the error message returned by mail.ParseAddress() function. This function takes a string value as an argument and parses according to the RFC 5322 address rules. It returns a struct type Address object and an error interface object replenished with a string message. The ParseAddress is a function found in the mail package.

We can create our own error object with a custom error message using the errors.New function. Let’s modify the above program to display our own custom error message:

package main

import (
	"errors"
	"fmt"
	"net/mail"
)

func isMailAddressValid(email string) (string, bool) {
	addr, err := mail.ParseAddress(email)
	customErrMsg := errors.New("please provide a valid email address")
	if err != nil {		
		return customErrMsg.Error(), false
	}
	return addr.Address, true
}

func main() {
	em, ok := isMailAddressValid("mymail**gmail.com")
	if ok {
		fmt.Println(em)
	} else {
		fmt.Println(em)
	}
}

Once more, running this code in your code editor will result in the following output:

please provide a valid email address

Error Handling in Go with the fmt.Errorf function

There is another function in the fmt package called fmt.Errorf. This function enables us to create error messages dynamically and formats the error message according to the format specifier, returning a string value. The function takes a string argument with a placeholder much like the function fmt.printf.

According to the Go documentation: “if the format specifier includes a %w verb with an error operand, the returned error will implement an Unwrap method returning the operand. It is invalid to include more than one %w verb or to supply it with an operand that does not implement the error interface. The %w verb is otherwise a synonym for %v.”

Here is a quick example with a slight modification of the above code:

package main

import (
	"fmt"
	"net/mail"
)

func isMailAddressValid(email string) (string, bool) {
	addr, e := mail.ParseAddress(email)

	if e != nil {
		err := fmt.Errorf("you provided %s, valid format is [email protected]", email)
		return err.Error(), false
	}
	return addr.Address, true
}

func main() {
	em, ok := isMailAddressValid("mymail**gmail.com")
	if ok {
		fmt.Println(em)
	} else {
		fmt.Println(em)
	}
}

Here is the output of the above code:

you provided mymail**gmail.com, valid format is [email protected]

Go Function Returning Error Values

In practice, an error is returned from a function when something goes wrong. The callers of the function typically use an if statement to see the occurrence of an error or nil value, which essentially means no error has occurred. A function that returns a single error value only to denote some stateful changes – such as if the socket connection is successful or database row changes have occurred and so forth. A Function commonly returns an error value to indicate its success or to indicate an error which simply means the function has failed. Go programming allows a function to return more than one value. For example, the following intDiv function returns the result of an integer division of two values – a numerator and a denominator. An error is returned along with an invalid value (for example, -999) if the denominator value is 0 (because dividing by zero is not allowed). If everything is fine then a nil is returned as an error value.

package main

import (
	"errors"
	"fmt"
)

func intDiv(num, denom int) (int, error) {
	if denom == 0 {
		return -999, errors.New("divide by zero is no allowed")
	}
	return num / denom, nil
}

func main() {
	n := 20
	d := 0

	result, err := intDiv(n, d)
	if err == nil {
		fmt.Println("Result : ", result)
	} else {
		fmt.Println(err.Error())
	}
}

Here is the result of running the above Go code sample:

divide by zero is no allowed

It is but a convention that the error returned by the function is the last item in the event that a function returns multiple values.

Using Anonymous Functions for Error Handling in Go

We can use anonymous functions to reduce boilerplate codes in error handling. The Following is a slight modification of the above code for handling errors with anonymous functions in Go:

package main

import (
	"errors"
	"fmt"
)

func intDiv(num, denom int) (int, error) {

	he := func(err error) (int, error) {
		return -999, err
	}
	if denom == 0 {
		return he(errors.New("divide by zero is no allowed"))
	}
	return num / denom, nil
}

func main() {

	n := 20
	d := 3

	result, err := intDiv(n, d)
	if err == nil {
		fmt.Println("Result : ", result)
	} else {
		fmt.Println(err.Error())
	}

}

Go Error Handling Using Blank Identifier

Go enables developers to completely ignore an error as it is received from a function. It seems not a very good idea yet sometimes it may be necessary. For example, we may receive the result from the integer division in the above code but ignore receiving the error. Here is an example of using a blank identifier in Go:

//...

func main() {
	n := 20
	d := 3
	result, _ := intDiv(n, d)	
	fmt.Println("Result : ", result)
}

The underscore (_) means a blank identifier, which can be assigned or declared with any value of any type, with the value discarded harmlessly. In the above code, we require assignment of multiple values on the left side. Since we want to ignore the error value we can use the underscore(_). It helps to avoid creating dummy variables and makes it clear the fact that the value is to be discarded. So, syntactically, the following is also correct:

//...
	_, err := intDiv(n, d)	
//...

However, the following is incorrect:

//...
	_, _ := intDiv(n, d)	// not allowed
//...

We may, however, write it as follows, which means completely discarding anything returned by the function:

//...
	intDiv(n, d)	// OK
//...

Go Error Handling Techniques

As we can see, the Go programming language provides many ways to create errors through the standard library and many ways to build functions that can take care of the error and return them to the caller. It is also possible to create and handle more complex customized errors according to the need of the developer. This flexibility is inherent in Golang and we’ll go into those details in a later writeup. Here, we glimpsed quickly the error handling mechanisms implemented in Go with some relevant examples.

In the meantime, feel free to read more tutorials on Golang programming:

  • Methods in Go Explained
  • Arrays and Slices in Go
  • Working with Math in Go
  • Working with Strings in Go

Понравилась статья? Поделить с друзьями:
  • Gnutls error in the pull function debian 11
  • Gnutls error 8 a packet with illegal or unsupported version was received
  • Gnutls error 15 filezilla
  • Gnutls error 15 an unexpected tls packet was received
  • Gnuplot error while loading shared libraries libqt5core so 5