Custom Error

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 errorspackage Newfunctions.

In using the New function before you create a custom error, we take a look at Newis how to achieve. As shown below, a errorspackage of the Newimplementation 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
}

NewImplementation of the function is very simple. errorStringIs a structure type, there is only one string field s. Line 14 uses a errorStringpointer to a recipient (Pointer Receiver), to implement errorthe interface Error() string method .

Line 5 Newfunction has a string parameter, this parameter to create a errorStringvariable of type and returns its address. So it creates and returns a new error.

Now we already know Newhow the function works, we began to use in a program Newto 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)
}

Running on glayground

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 nilof an error (line 13).

In the mainfunction, 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 fmtpackage Errorfa function of. ErrorfThe format specifier function, a predetermined format errors, and returns the error meets a string .

Next we use the Errorffunction 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)
}

Running on the playground

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 errorbody 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 Errorthe 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 radiusfield, which stores the radius related to an error, the errfield stores the actual error message.

The next step is to implement errorthe 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 errorthe interface Error() stringmethod. And prints out the method described with respect to the radius of the error.

Let's write mainfunction and the circleAreafunction 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)
}

Running on the playground

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 areaErrorvalue type, then the return areaErroraddress value at the same time areaequal 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 main26 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 *areaErrortype. If the error is a \*areaErrortype, we can use it err.radiusto 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 errorthe 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() stringreturn to the description of the error process. When lengthless than zero, lengthNegative() boolthe method returns true, and when widthsmaller than zero, widthNegative() boolthe 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 rectAreafunction checks the length or width is less than zero, if less than zero, rectAreareturns an error message, otherwise it rectAreareturns a value of area of a rectangle and nilerror.

Let's create maina 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 mainprocess, we examined whether the error is nil(line 4). If the value is not an error nil, we will the next line assertion *areaErrortype. 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)
}

Running on the playground

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 Newfunction to create a custom error
  • Use Errorto 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.





Guess you like

Origin www.cnblogs.com/hualou/p/12069838.html