https://play.golang.org/p/FUS2-CcHflX
The more I played with the code, the more I have to agree with the commenter. This is not obvious behavior.
You can also get into obscure behavior if your implementation does not have a pointer receiver. Take this code for example: https://play.golang.org/p/MjjGMAZL3-v How can I get a nil pointer immediately after I checked whether it was nil? This one, I do know has bitten me before. Infrequently, but it has.
func (c *GZipComprosser) compress() []byte {
if (c == nil) {
return []byte{}
}
return []byte{c.internal}
}
?I don't think that's common at all (1) nor is it a sane burden to put on developers.
(1) https://github.com/golang/go/blob/master/src/bytes/buffer.go...
Better way is what you described, accept nil state as invalid, require user to handle it (user must initialize before using your method)
Or not.
1. Checking for nil receivers is rare and hardly idiomatic. (Although I have seen methods that are designed to work with nil receivers)
2. (*T)nil != nil is surprising.
A newbie looking at this code would not expect it to crash which is why I consider it a wart. In this specific case, the code was structured such that if the compressor was nil then no compression would happen. Then in some, hard to remember case, when you opted into gzip the whole thing would crash. I think I had been writing Go for about 18 months at that point and that snippet got past review. Ultimately the design had problems, (depending on `nil` to mean anything was probably dangerous and it's clearer to give NoCompression it's own type) so I'm not really arguing that the above snippet should work.
Once you understand why it's there it makes sense, but ultimately I think it's an unfortunate side effect of designing a language with nullable types.
I think newcomers are exposed to this behaviour now. For instance, it is step 12 in the tour of Go:
https://tour.golang.org/methods/12
I learnt Go before the tour was available and learnt a lot from going through the tour later on.
In Java land at some point we were taught to never use null anywhere, instead use the null object pattern.
And in Go I'd like to extend that, never call a method on a nil receiver if you can avoid it. I think it should be up to the caller to do the nil check, IF the receiver can ever be nil.
Hahaha oh you sweet summer child. It's considered a feature.
And since typed nils will never get fixed despite being an actual wart (though the FAQ tells you you're holding it wrong you idiot: https://golang.org/doc/faq#nil_error) there's no chance nil receivers will get removed from the language.
you also end up with things like this: https://play.golang.org/p/wgaLGOqFDZ9