Go series of tutorials - 31. Custom Error
Create a custom error by using the New function
Creating custom error easiest way is to use the errors
package New
functions.
In using the New function before you create a custom error, we take a look at New
is how to achieve. As shown below, a errors
package of the New
implementation of the function.
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
New
Implementation of the function is very simple. errorString
Is a structure type, there is only one string field s
. Line 14 uses a errorString
pointer to a recipient (Pointer Receiver), to implement error
the interface Error() string
method .
Line 5 New
function has a string parameter, this parameter to create a errorString
variable of type and returns its address. So it creates and returns a new error.
Now we already know New
how the function works, we began to use in a program New
to create a custom error bar.
We will create a simple program to calculate the radius of the circle, if the radius is negative, it will return an error.
package main
import (
"errors"
"fmt"
"math"
)
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, errors.New("Area calculation failed, radius is less than zero")
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Area of circle %0.2f", area)
}
In the above procedure, we check if the radius is less than zero (line 10). If the radius is less than zero, we will return to the area is equal to 0, and the corresponding error message. If the radius is greater than zero, it will calculate the area, and the return value nil
of an error (line 13).
In the main
function, we check for errors on line 19 is equal nil
. If not nil
, we will print out the error and return it, otherwise we will print the circular area.
In our program, the radius is less than zero, so print out:
Area calculation failed, radius is less than zero
Use Errorf add more information to the error
The above program works well, but if we can print out the current radius of the circle, so much the better. This use to fmt
package Errorf
a function of. Errorf
The format specifier function, a predetermined format errors, and returns the error meets a string .
Next we use the Errorf
function to improve our program.
package main
import (
"fmt"
"math"
)
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, fmt.Errorf("Area calculation failed, radius %0.2f is less than zero", radius)
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Area of circle %0.2f", area)
}
In the above procedure, we use Errorf
(line 10) print radius error occurred. Running the program will output:
Area calculation failed, radius -20.00 is less than zero
For more information on using a structure and provide the error field
Error may also be used to achieve the error
interfaces structure represented. This way we can more flexibly handle errors. In the above example, if we want to access that caused the error radius, and now the only way is to parse the description of the error message Area calculation failed, radius -20.00 is less than zero
. Doing so is not very good, because once described information changes, the program will go wrong.
We will use the standard library used, "asserted the underlying structure type, use the structure for more information field" in a tutorial on this section, we explain this method can be used to access the structure fields caused error radius. We will create an implementation error
body type structure of the interface, and use it in the field to provide more information about the error.
The first step is to create a structure type indicates an error. The wrong type of naming convention is name to Error
the end. So we might as well put a structure type named areaError
.
type areaError struct {
err string
radius float64
}
The above structure has a type radius
field, which stores the radius related to an error, the err
field stores the actual error message.
The next step is to implement error
the interface.
func (e *areaError) Error() string {
return fmt.Sprintf("radius %0.2f: %s", e.radius, e.err)
}
In the above code, we use the pointer receiver *areaError
, implements error
the interface Error() string
method. And prints out the method described with respect to the radius of the error.
Let's write main
function and the circleArea
function to complete the entire program.
package main
import (
"fmt"
"math"
)
type areaError struct {
err string
radius float64
}
func (e *areaError) Error() string {
return fmt.Sprintf("radius %0.2f: %s", e.radius, e.err)
}
func circleArea(radius float64) (float64, error) {
if radius < 0 {
return 0, &areaError{"radius is negative", radius}
}
return math.Pi * radius * radius, nil
}
func main() {
radius := -20.0
area, err := circleArea(radius)
if err != nil {
if err, ok := err.(*areaError); ok {
fmt.Printf("Radius %0.2f is less than zero", err.radius)
return
}
fmt.Println(err)
return
}
fmt.Printf("Area of rectangle1 %0.2f", area)
}
In the above procedure, circleArea
(line 17) for calculating the area of a circle. The function first checks radius is less than zero, is less than zero, it will pass the error message and the corresponding error radii, creates a areaError
value type, then the return areaError
address value at the same time area
equal to zero (line 19). So we provide error information (i.e., caused the error radius), we used a custom error fields of the structure defined in it .
If the radius is not negative, the function calculates and returns the area in line 21, and the error value nil
.
In the main
26 line of the function, we try to calculate the area of a circle of radius-20. Since the radius is less than zero, thus causing an error.
We checked in on line 27 whether the error nil
, and asserts that the next line *areaError
type. If the error is a \*areaError
type, we can use it err.radius
to get the error radius (line 29), custom error messages printed out, and finally return to exit the program .
If the assertion wrong, we are in the first row 32 print the error and return. If no errors occur, the line 35 will print area.
The program will output:
Radius -20.00 is less than zero
Let's use the previous tutorial mentioned second method , more information on using custom error type methods provide wrong.
For more information on the type of structure using the method to provide error
In this section, we will write a program to calculate the area of a rectangle. If the length or width of less than zero, the program prints the error.
The first step is to create a false representation structure.
type areaError struct {
err string //error description
length float64 //length which caused the error
width float64 //width which caused the error
}
The above structure type field in addition to a description of the error, and may lead to wrong width and height.
Now that we have the wrong type, we have to implement error
the interface, and the type of error to add two methods, it provides more error messages.
func (e *areaError) Error() string {
return e.err
}
func (e *areaError) lengthNegative() bool {
return e.length < 0
}
func (e *areaError) widthNegative() bool {
return e.width < 0
}
In the above code fragment, from the Error() string
return to the description of the error process. When length
less than zero, lengthNegative() bool
the method returns true
, and when width
smaller than zero, widthNegative() bool
the method returns true
. Both methods provide more information about the error and where it prompts the reason we failed to calculate the area (length or width of a negative number is negative). So we have two of the wrong type structure methods, to provide more error messages .
The next step is to write a function to calculate the area.
func rectArea(length, width float64) (float64, error) {
err := ""
if length < 0 {
err += "length is less than zero"
}
if width < 0 {
if err == "" {
err = "width is less than zero"
} else {
err += ", width is less than zero"
}
}
if err != "" {
return 0, &areaError{err, length, width}
}
return length * width, nil
}
The above rectArea
function checks the length or width is less than zero, if less than zero, rectArea
returns an error message, otherwise it rectArea
returns a value of area of a rectangle and nil
error.
Let's create main
a function to complete the entire program.
func main() {
length, width := -5.0, -9.0
area, err := rectArea(length, width)
if err != nil {
if err, ok := err.(*areaError); ok {
if err.lengthNegative() {
fmt.Printf("error: length %0.2f is less than zero\n", err.length)
}
if err.widthNegative() {
fmt.Printf("error: width %0.2f is less than zero\n", err.width)
}
return
}
fmt.Println(err)
return
}
fmt.Println("area of rect", area)
}
In the main
process, we examined whether the error is nil
(line 4). If the value is not an error nil
, we will the next line assertion *areaError
type. Then, we use lengthNegative()
and widthNegative()
method, check for errors because the length of a width less than zero or less than zero. So we are using the wrong type of structure methods to provide more error messages.
If no error occurs, it will print area of a rectangle.
Here is the code for the entire program for your reference.
package main
import "fmt"
type areaError struct {
err string //error description
length float64 //length which caused the error
width float64 //width which caused the error
}
func (e *areaError) Error() string {
return e.err
}
func (e *areaError) lengthNegative() bool {
return e.length < 0
}
func (e *areaError) widthNegative() bool {
return e.width < 0
}
func rectArea(length, width float64) (float64, error) {
err := ""
if length < 0 {
err += "length is less than zero"
}
if width < 0 {
if err == "" {
err = "width is less than zero"
} else {
err += ", width is less than zero"
}
}
if err != "" {
return 0, &areaError{err, length, width}
}
return length * width, nil
}
func main() {
length, width := -5.0, -9.0
area, err := rectArea(length, width)
if err != nil {
if err, ok := err.(*areaError); ok {
if err.lengthNegative() {
fmt.Printf("error: length %0.2f is less than zero\n", err.length)
}
if err.widthNegative() {
fmt.Printf("error: width %0.2f is less than zero\n", err.width)
}
return
}
fmt.Println(err)
return
}
fmt.Println("area of rect", area)
}
The program will print out:
error: length -5.00 is less than zero
error: width -9.00 is less than zero
In the previous tutorial, error handling , we introduce three ways to provide more information about the error, which we've now seen two examples.
The third method uses a direct comparison is relatively simple. I left as an exercise, you can try to use this method to give more information from the definition wrong.
This tutorial is over.
A quick overview of the contents of this tutorial:
- Use
New
function to create a custom error - Use
Error
to add more error messages - Using a structure and fields, to provide more information about the error
- Using a structure and method for providing error information
wish you happiness.