Elegantly handle errors returned by deferred functions

As a GoLang developer you would have seen this code snippet very often:

resource, err = some.Resource()
if err != nil {
    log.Fatal("error", err.Error())
}

defer resource.Close()

// do something with the resource

Code similar to the example snippet above is seen when dealing with resources like database connections and files. While nothing seems wrong with this code (there is really nothing wrong here to be honest), some of the IDEs or static analysis tools will report unhandled error warning on line

defer resource.Close()

There are different trains of thought on how to deal with this error. In most of the places, such errors can be safely ignored because they don’t matter. At other times, even if the error did matter, there was no proper way to handle it. For example, if there is an error while closing a database connection, there is no good way to handle this. Even if we are not in a position to handle this error, logging it is a good practice.

The following snippet of code will help us overcome the problems stated above i.e. get rid of IDE warnings / static analysis errors and also be able to handle / log such errors

func Close(close io.Closer) {
    err := close.Close()
    if err != nil {
        log.Println("error occurred while trying to close resource", err.Error())
    }
}

The above function accepts an object implementing the io.Closer interface, calls the close function and handles the error gracefully. With this new helper, we can rewrite our original snippet as:

resource, err = some.Resource()
if err != nil {
    log.Fatal("error", err.Error())
}

defer Close(resource)

// do something with the resource

Leave a Reply

Your email address will not be published. Required fields are marked *