Welcome To Golang By Example

Menu
  • Home
  • Blog
Menu

Understanding Errorf function in Go (Golang)

Posted on April 29, 2023April 29, 2023 by admin

Table of Contents

  • Overview
    • Formatting a string variable
    • Formatting an integer
    • Formatting a struct
  • Wrapping of error

Overview

Errorf function is defined in the fmt package and is used to create a custom error with a formatted message as per the format specifier provided.

https://golang.org/pkg/fmt/#Errorf

  • Its main use is to create a custom error in golang with a formatted message.
  • It is also used to create a custom error which can wrap another error provided to it. In golang, an error can wrap another error as well.  What does the wrapping of error mean? It means to create a hierarchy of errors in which a  particular instance of error wraps another error and that particular instance itself can be wrapped inside another error. We will see about this in detail later in this tutorial.

Below is the function prototype of Errorf

func Errorf(format string, a ...interface{}) error

As you can see it returns an instance of the error.

Errorf is also a variadic function meaning that it can have multiple arguments. There are two important points about its argument list

  • Notice that the first argument is a format or template string.
  • The next is a variable number of arguments. Each of the arguments in this list could be string, int, struct, or anything. That is why it is an empty interface

Errrof formats the string using custom specifiers. The first argument that is the format or template string contains the actual string that needs to be formatted plus some formating verbs. These formating verbs tell how the trailing arguments will be formatted in the final string.  So basically the format string argument contains certain symbols which are replaced by trailing arguments. 

Eg 

Formatting a string variable

  • %s symbol is used
  • Example 
name := "J"
fmt.Errorf("Name has less then 3 character. Name: %s\n", name)

Formatting an integer

  • %d symbol is used
  • Example 
age := 0
fmt.Errorf("Age is 0: Age:%d\n", age)

Formatting a struct

For example, there are three format specifiers for printing a struct.

  • %v – It will print only values. The field name will not be printed. This is the default way of printing a struct when using Println
  • %+v – It will print both field and value. 
  • %#v – It will print the struct, also both field name and value

That is why

fmt.Errorf("Employee not found. Details: %v\n", e)
fmt.Errorf("Employee not found. Details: %+v\n", e)
fmt.Errorf("Employee not found. Details: %#v\n", e)

returns an error with below formatted message respectively

Here is the working program for the same

package main
import (
"fmt"
)
type employee struct {
Name string
Age int
}
func main() {
sampleErr := "database connection issue"
err := fmt.Errorf("Err is: %s", sampleErr)
fmt.Println(err)
port := 8080
err = fmt.Errorf("Err is: %s to port %d", sampleErr, port)
fmt.Println(err)
e := employee{
Name: "John",
}
err = fmt.Errorf("Employee not found. Details %v", e)
fmt.Println(err)
err = fmt.Errorf("Employee not found. Details %+v", e)
fmt.Println(err)
err = fmt.Errorf("Employee not found. Details %#v", e)
fmt.Println(err)
}

Output

Err is: database connection issue
Err is: database connection issue to port 8080
Employee not found. Details {John 0}
Employee not found. Details {Name:John Age:0}
Employee not found. Details main.employee{Name:"John", Age:0}

Notice that in below Errorf

err = fmt.Errorf("Err is: %s to port %d", sampleErr, port)
  • %s is replaced by sampleErr.
  • %d is replaced by port.

So basically the symbols or verbs in the format string argument are replaced by trailing arguments in order

If the number of format specifiers in the format string does not match the number of next variable arguments then the format specifier will be printed as is. For example, in the below code, we have two format specifier

  • %s
  • %d

While the next variable number of arguments is only one. Hence when we format it then it returns the formatted error with second format specifier as is with MISSING as a warning

package main
import "fmt"
func main() {
name := "John"
err := fmt.Errorf("Employee not found with name: %s and age %d", name)
fmt.Println(err)
}

Output

Employee not found with name: John and age %!d(MISSING)

Wrapping of error

Below is the syntax for wrapping an error

e := fmt.Errorf("... %w ...", ..., err, ...)

%w directive Is used for wrapping the error.  The fmt.Errorf should be called with only one %w directive. Let’s see an example.

package main
import (
"fmt"
)
type errorOne struct{}
func (e errorOne) Error() string {
return "Error One happened"
}
func main() {
e1 := errorOne{}
e2 := fmt.Errorf("E2: %w", e1)
e3 := fmt.Errorf("E3: %w", e2)
fmt.Println(e2)
fmt.Println(e3)
}

Output

E2: Error One happened
E3: E2: Error One happened

In the above program, we created a struct errorOne that has an Error method hence it implements the error interface. Then we created an instance of the errorOne struct named e1. Then we wrapped that instance e1 into another error e2 like this

e2 := fmt.Errorf("E2: %w", e1)

Then we wrapped e2 into e3 like below. 

e3 := fmt.Errorf("E3: %w", e2)

So so we created a hierarchy of errors in which e3 wraps e2 and e2 wraps e1.  Thus e3 also wraps e1 transitively. When we print e2  it also prints the error from e1 and gives the output.

E2: Error One happened

When we print e3 it prints the error from e2 as well as e1 and gives the output.

E3: E2: Error One happened

You can read about wrapping and unwrapping of error in detail here

/wrapping-and-unwrapping-error-golang/

This is all about the Errorf function. Hope you have liked this article. Please share feedback in the comments. Also, check out our Golang advance tutorial Series – Golang Advance Tutorial

  • errorf
  • go
  • golang
  • Popular Articles

    Golang Comprehensive Tutorial Series

    All Design Patterns in Go (Golang)

    Slice in golang

    Variables in Go (Golang) – Complete Guide

    OOP: Inheritance in GOLANG complete guide

    Using Context Package in GO (Golang) – Complete Guide

    All data types in Golang with examples

    Understanding time and date in Go (Golang) – Complete Guide

    ©2023 Welcome To Golang By Example | Design: Web XP