Go series of tutorials - 30. Error Handling

Welcome to  Golang tutorial series on the 30.

What is wrong?

Error indicates that the program appears in unusual circumstances. For example, when we try to open a file, the file system actually does not have this file. This is an abnormal situation, it is represented by an error.

In Go, the error has been very common. Wrong with the built-in  error types to represent.

Like other built-in types (such as  int, float64 etc.), error values can be stored in a variable, as the return value of the function and so on.

Examples

Now we begin to write an example, the program tries to open a file that does not exist.

package main

import ( "fmt" "os" ) func main() { f, err := os.Open("/test.txt") if err != nil { fmt.Println(err) return } fmt.Println(f.Name(), "opened successfully") } 

 

In line 9 program, we try to open the path for the  /test.txt file (playground is clearly not the existence of this document). os Bag  Open function has the following signature:

func Open(name string) (file *File, err error) 

If you successfully open the file, Open the function returns a file handle (File Handler) and a value  nil of the error. The error occurs when you open a file, it will return an equal  nil wrong .

If a function  or method  returns an error, as usual, the last error is returned as a value. So  Open also a function will  err as a final return value.

Go accordance with the practice in dealing with errors, the errors are usually returned by  nil comparison. nil Value indicates that no error has occurred, rather than the  nil value of an error has occurred . Here we line 10 checks whether the error value  nil. If not  nil, we will simply print out the error and  mainreturn to function.

Run the program will output:

open /test.txt: No such file or directory

Great! We got an error that indicates that the file does not exist.

The wrong type of representation

Let us further in-depth understanding  error of how type is defined. error A is an interface type, defined as follows:

type error interface { Error() string } 

error With a signature for the  Error() string method. All types implement this interface can be used as a type of error. Error() The method gives a description of the error.

fmt.Println When printing error, it internally calls the  Error() string method to get a description of the error. On a line 11 in the example, so that prints an error is described.

For more information from the error of different methods

Now, we know that  error is an interface type, let's look at how to get more information from an error.

In the previous example, we just print out the description of the error. If we want to know the wrong file path, how to do it? One option is to directly parse error string. This is the output from the previous example:

open /test.txt: No such file or directory

We resolved this error message, although the acquired file path error, but this method is very elegant. With the language version of the update, this description of the error are likely to change at any time, so that our program error .

Is there a more reliable way to get the file name of it? The answer is yes, it can be done, Go standard library gives various methods to extract information about the error. We see it one by one.

1. The type of assertion underlying structure, field structure used for more information

If you carefully read the  Open documentation for the function, you can see the type of error it returns  *PathError. PathError Is a structure type, it is implemented in the standard library as follows:

type PathError struct { Op string Path string Err error } func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } 

If you are interested in knowing the position of the source code appears, can be found here: https://golang.org/src/os/error.go?s=653:716#L11.

Through the above code, you will know  *PathError by declaring  Error() string methods to achieve the  error interface. Error() string The file operations, the error path and the actual splicing, and returns the string. So we get the error message:

open /test.txt: No such file or directory

The structure  PathError of the  Path field, have led to the wrong file path. Modify the program in front of us write, print out the path.

package main

import ( "fmt" "os" ) func main() { f, err := os.Open("/test.txt") if err, ok := err.(*os.PathError); ok { fmt.Println("File at path", err.Path, "failed to open") return } fmt.Println(f.Name(), "opened successfully") } 

 

In the above procedure, we use the line 10 type of assertion (Type Assertion) to get the  error underlying value of the interface (Underlying Value). Next in line 11, we used  err.Path to print the path. The program will output:

File at path /test.txt failed to open

Great! We have successfully acquired the type of assertion to the wrong file path to use.

2. The assertion underlying structure type, method call for more information

For more information about the second error method, but also the underlying type of assertion, then, to get more information on the structure by type of method calls.

Let's understand this with an example.

Standard library  DNSError structure type is defined as follows:

type DNSError struct { ... } func (e *DNSError) Error() string { ... } func (e *DNSError) Timeout() bool { ... } func (e *DNSError) Temporary() bool { ... } 

It can be seen from the above code, DNSError as well as the structure  Timeout() bool and the  Temporary() bool two methods, which returns a Boolean value indicating whether the error is caused by a timeout, or a temporary error.

Next we write a program that assertion  *DNSError types, and call these methods to determine if the error is a temporary error, or caused by a timeout.

package main

import ( "fmt" "net" ) func main() { addr, err := net.LookupHost("golangbot123.com") if err, ok := err.(*net.DNSError); ok { if err.Timeout() { fmt.Println("operation timed out") } else if err.Temporary() { fmt.Println("temporary error") } else { fmt.Println("generic error: ", err) } return } fmt.Println(addr) } 

Note: You can not perform DNS resolution in the playground. Run this program in your local .

In the process, we in line 9, trying to get  golangbot123.com(invalid domain name) of ip. In line 10, we pass  *net.DNSError the type of assertion, access to the wrong underlying value. The next line 11 and line 13, we were checking the error is caused by a timeout, or a temporary error.

In the present embodiment, the error we neither temporary error, is not caused by a timeout, and therefore the output of the program:

generic error:  lookup golangbot123.com: no such host

If the error is a temporary error, or triggered by a timeout, then the corresponding if statement is executed, so that we can deal with them appropriately.

3. Direct comparison

A third way to get more information about the error, is the  error direct comparison of a variable of type. We come to understand through an example.

filepath Package  Glob for the return of all documents meet the glob pattern. If you write the wrong mode, the function will return an error  ErrBadPattern.

filepath Package  ErrBadPattern is defined as follows:

var ErrBadPattern = errors.New("syntax error in pattern") 

errors.New() For creating a new error. We will discuss it in detail in the next tutorial.

When the mode is incorrect, Glob the function will return  ErrBadPattern.

Let's write a little program to look at this error.

package main

import ( "fmt" "path/filepath" ) func main() { files, error := filepath.Glob("[") if error != nil && error == filepath.ErrBadPattern { fmt.Println(error) return } fmt.Println("matched files", files) } 

 

In the program, we query the mode  [ of the file, but this mode written incorrectly. We examined whether the error is  nil. To get more information about the error, we are in the first 10 rows  error directly  filepath.ErrBadPattern compared. If this condition is met, then the error is caused by the wrong mode. The program will output:

syntax error in pattern

When the standard library provides details of the error, using the above-mentioned three methods. In the next tutorial, we'll create our own custom error by these methods.

Error can not be ignored

Never ignore the error. Ignore the error cause problems. Next, I rewrite the above example, when listing all filenames to meet the model, I've omitted error handling code.

package main

import ( "fmt" "path/filepath" ) func main() { files, _ := filepath.Glob("[") fmt.Println("matched files", files) } 

 

We already know this model is wrong from the previous example. In line 9, by using the  _ blank identifier, I ignore the  Glob error returned by the function. I simply print all matching files on line 10. The program will output:

matched files []

Since I ignored the error, the output looks like there is no matching the glob pattern file, but in fact it is not because the writing mode. So Never ignore the error.

This tutorial is over.

This tutorial we discussed how to handle the error occurred in the program, and also discussed how to find more information about the error. A quick overview of the contents of this tutorial:

  • What is wrong?
  • False representation
  • Get error details of the various methods
  • Error can not be ignored

In the next tutorial, we will create our own custom error and standard error to add more context (Context).

wish you happiness.

Guess you like

Origin www.cnblogs.com/fengchuiyizh/p/11356121.html