Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to `catch` specific errors

For example, I am using one Go standard library function as:

func Dial(network, address string) (*Client, error)

This function may return errors, and I just care about errors which report "connection lost" or "connection refused", then do some code to fix these.
It seems like:

client, err := rpc.Dial("tcp", ":1234")  
if err == KindOf(ConnectionRefused) {
  // do something
}

What's more, how to get all the errors a specific standard library function may return?

like image 633
fding Avatar asked Apr 25 '17 08:04

fding


People also ask

How do I catch a specific exception?

The order of catch statements is important. Put catch blocks targeted to specific exceptions before a general exception catch block or the compiler might issue an error. The proper catch block is determined by matching the type of the exception to the name of the exception specified in the catch block.

How do you catch specific errors in Python?

Catching Specific Exceptions in Python A try clause can have any number of except clauses to handle different exceptions, however, only one will be executed in case an exception occurs. We can use a tuple of values to specify multiple exceptions in an except clause.

How do you catch specific errors in node JS?

Using try-catch-finally. js, you can call the _try function with an anonymous callback, which it will call, and you can chain . catch calls to catch specific errors, and a . finally call to execute either way.


2 Answers

There's no standard way to do this.

The most obvious way, which should only be used if no other method is available, is to compare the error string against what you expect:

if err.Error() == "connection lost" { ... }

Or perhaps more robust in some situations:

if strings.HasSuffix(err.Error(), ": connection lost") { ... }

But many libraries will return specific error types, which makes this much easier.

In your case, what's relevant are the various error types exported by the net package: AddrError, DNSConfigError, DNSError, Error, etc.

You probably care most about net.Error, which is used for network errors. So you could check thusly:

if _, ok := err.(net.Error); ok {
    // You know it's a net.Error instance
    if err.Error() == "connection lost" { ... }
}

What's more, how to get all the errors a specific standard library function may return?

The only fool-proof way to do this is to read the source for the library. Before going to that extreme, a first step is simply to read the godoc, as in the case of the net package, the errors are pretty well documented.

like image 77
Flimzy Avatar answered Sep 21 '22 01:09

Flimzy


You can now use the errors.Is() function to compare some standard errors:

client, err := net.Dial("tcp", ":1234")
if errors.Is(err, net.ErrClosed) {
    fmt.Println("connection has been closed.")
}

A common file opening scenario:

file, err := os.Open("non-existing");
if err != nil {
    if errors.Is(err, fs.ErrNotExist) {
        fmt.Println("file does not exist")
    } else {
        fmt.Println(err)
    }
}

UPDATE
You can also use errors.As() if you'd like to check the error type:

client, err := net.Dial("tcp", ":1234")
var errC = net.ErrClosed
if errors.As(err, &errC) {
    fmt.Printf("connection has been closed: %s", errC)
}
client.Close()

A more detailed explanation can be found in the Go Blog.

like image 33
17xande Avatar answered Sep 17 '22 01:09

17xande