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 main
return 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.