This is a quick post to discuss an interesting bug that was recently unearthed by go vet .

The following code is a simplified reduction of a larger piece of code. In the original code the if statement was much larger, encompassing several complicated conditions, making the bug hard to spot visually.

package main import "fmt" import "io" type Thing struct { Reader_ io.Reader } func (t *Thing) Reader() io.Reader { return t.Reader_ } func main() { t := Thing{Reader_: nil} if t.Reader != nil { fmt.Println("wait a second") } }

Running this code gives the result

% go run thing.go wait a second

But … what is going on ? Thing.Reader_ is explicitly set to nil (even though this is unnecessary, the zero value of an interface field is nil ), so how can the check for nil on the very next line fail?

Let’s look at what go vet thinks.

% go vet thing.go thing.go:14: comparison of function Reader != nil is always true exit status 1

The mistake in the original code was the author had intended to write t.Reader() , but perhaps forgot the parenthesis. The uncommon use of the underscore suffix possibly contributed to the bug.

So, a quick fix and a code review later and the bug was closed. But, why was this code valid in the first place ? The answer is, since Go 1.1, the expression t.Reader is no longer a syntax error, instead it evaluates to a Method Value.

Let’s look a little closer

t := Thing{Reader_: nil} fmt.Printf("Reader_: %T

", t.Reader_) fmt.Printf("Reader(): %T

", t.Reader()) fmt.Printf("Reader: %T

", t.Reader)

gives the following output

Reader_: <nil> Reader(): <nil> Reader: func() io.Reader