== In Go, sometimes a _nil_ is not a _nil_ Today I ran into what turns out to be [[a Go FAQ http://golang.org/doc/faq#nil_error]]. First, as a little Go quiz, see if you can tell what [[this program http://play.golang.org/p/gnBo9WmA89]] should print before you run it in the Go playground (I've put the program in a sidebar in case it ever goes away on the playground). The core of the program is this code: .pn prewrap on type fake struct { io.Writer } func fred (logger io.Writer) { if logger != nil { logger.Write([]byte("...")) } } func main() { var lp *fake fred(nil) fred(lp) } Since Go variables are explicitly created with their zero values, which in the case of pointers such as _lp_ is _nil_, you would expect this code to run (but do nothing). In fact it crashes on the second call to _fred()_. What is happening is that sometimes in Go what started out as a _nil_ value and will look like a _nil_ value if you print it straightforwardly is not in fact a _nil_ value. In a nutshell, ~~Go distinguishes between _nil_ interface values and _nil_ values of concrete types that are converted to interfaces~~. Only the former is *really* _nil_ and so will compare equal to a plain _nil_, as _fred()_ attempts to do here. (As a corollary of this, your concrete methods on _(f *fake)_ can get called with a _nil_ _f_ value. It may be a _nil_ pointer, but it's a *typed* _nil_ pointer and so it can have methods. It can even have methods through interfaces, as is the case here.) For the situation I found myself in, the way to deal with this is to change the setup procedure. The real program set up _fake_ conditionally, something like: > var l *sLogger > > if smtplog != nil { > l = &sLogger > l.prefix = logpref > l.writer = bufio.NewWriterSize(smtplog, 4096) > } > convo = smtpd.NewConvo(conn, l) This passes a _nil_ of the concrete type '_* sLogger_' to something that expected an _io.Writer_, causing interface conversion and hiding the _nil_. To get around it we can just add a level of indirection with an _io.Writer_ variable that must be explicitly set: > var l2 io.Writer > > if smtplog != nil { > l := &sLogger > l.prefix = logpref > l.writer = .... > l2 = l > } > convo = smtpd.NewConvo(conn, l2) If we are not initializing our special logging, _l2_ stays a pure and real _io.Writer_ _nil_ and will be detected as such down in the depths of the code in the _smtpd_ package. (You can do a similar trick by pulling the setup out into a function that has a return type of _io.Writer_ and explicitly returns a _nil_ in the case of no logging. But you have to return the interface type; if you give your setup function a return type of '_* sLogger_' you'll have the same problem all over again.) It's a matter of taste if you want to keep _nil_ guard code in your _sLogger_ method functions. In the end I decided that I didn't want to; if I get this sort of initialization wrong in the future in this code, I want a crash so I can fix it. The other lesson I've learned from this is that if I'm printing values for debugging purposes where I might run into this issue I don't want to use _%v_ as the format specifier, I want to use _%#v_. The former will print a plain and misleading '__' for both the nil interface and nil concrete type cases, while the latter will print '__' for the former and something like '_``(*main.fake)(nil)''_' for the latter. === Sidebar: the test program package main import ( "fmt" "io" ) type fake struct { io.Writer } func fred(logger io.Writer) { if logger != nil { logger.Write([]byte("a test\n")) } } func main() { // this is born var t *fake fred(nil) fmt.Printf("passed 1\n") fred(t) fmt.Printf("passed 2\n") }