Assigning the returning error to an underscore

Viewed 421

I've been reading some Golang code from github.com/lib/pq which provides drivers for interacting with a postgres database.

Among the code I came across this:

go func() {
    select {
    case <-done:
        _ = cn.cancel()
        finished <- struct{}{}
    case <-finished:
    }
}()

The cancel function looks like:

func (cn *conn) cancel() error

As far as I can tell, the underscore isn't being used as a static assertion about a type (and therefore the compiler doesn't evaluate any side effects as far as I can see (as in this example)) and it isn't a second parameter whereby the author may want to discard it.

In summary: Why assign the result of the cancel function (the error) to an underscore?

2 Answers

Code must be correct. To be sure that code is correct, code must be readable.


The First Rule of Go: Check for errors.


func (cn *conn) cancel() error

If I write

cn.cancel()

did I forget to check for errors or did I decide to discard the error value?

However, if I write

_ = cn.cancel()

I did not forget to check for errors and I did decide to discard the error value.


The Go Programming Language Specification

Blank identifier

The blank identifier is represented by the underscore character _. It serves as an anonymous placeholder instead of a regular (non-blank) identifier and has special meaning in declarations, as an operand, and in assignments.

Assignments

The blank identifier provides a way to ignore right-hand side values in an assignment:

The blank identifier “_” is a special anonymous identifier. When used in an assignment, like this case, it provides a way to explicitly ignore right-hand side values. So, the developer has decided to ignore/discard the error returned from this method call.

A few reasons why they may have done this (based on a quick glance at the method call and context, my guess is 3 or 4):

  1. The method call is guaranteed to succeed in this context.
  2. The error is already handled sufficiently within the method call; no reason to handle it again.
  3. The error doesn’t matter (eg the relevant process is going to end anyway and the outcome will be the same as if the method call has succeeded without error).
  4. The developer was in a hurry to get something working, ignored the error to save time, then failed to come back and handle the error.
Related