First let's consider the following:
func process(body io.Reader) {
fmt.Printf("body == nil ? %+v\n", body == nil)
}
func main() {
var body *bytes.Buffer
fmt.Printf("body == nil ? %+v\n", body == nil)
process(body)
process(nil)
}
And here's the output:
body == nil ? true
body == nil ? false // Did you get this right?
body == nil ? true
Another example:
type Container struct {
Reader io.Reader
}
func processContainer(container Container) {
fmt.Printf("container.Reader == nil ? %+v\n", container.Reader == nil)
}
func main() {
var body *bytes.Buffer
processContainer(Container{Reader: body})
processContainer(Container{Reader: nil})
}
Output:
container.Reader == nil ? false // Did you get this right?
container.Reader == nil ? true
The explanation for this is at https://golang.org/doc/faq#nil_error.
A naive solution is to make the == nil
test just return true if the interface object contains nil
value. But this would violate transitivity of ==
, as it would assert two objects with nil value but different interface types true under ==
.
However, I wonder if there should be an IsNil()
method on all interface types, which would solve this issue?
Another example, this line from Go http client, can catch you unexpectedly:
https://github.com/golang/go/blob/master/src/net/http/client.go#L545
So if you call it like this
var body *bytes.Buffer
http.NewRequest(method, path, body)
You'll get a nil pointer exception, even though, by the look of the source code, this shouldn't happen.
Edit
Sorry I referenced the wrong line of the Go http source, now corrected. But the example still holds.
Edit 2
I've highlighted my question to make it clear what I'm asking.