Okay, but what was the rationale for designing the language like that?
func (o *Object) ReturnSomething() int {
if o == nil {
return 0
}
return o.SomeOtherValue
}
It is also therefore legal to return in an interface value a nil pointer to a struct of a particular kind, and therefore "an interface containing a nil pointer of a particular type" and "an interface containing nothing at all" are fundamentally different things that can not be collapsed together.So as Vendan says, it is just part of the language. All languages have this sort of wart in them, where two or more perfectly sensible decisions interact to create something that isn't sensible at first glance.
(I'm still in favor of going back in time and changing Go to have non-nillable values, but that ship has certainly sailed.)
The languages I'm used to don't even have `nil`.
> "nil" is a perfectly valid value for a pointer to have.
So, just like C and Java. I don't see the difference.
> You can write methods like this: (snippet)
Oh, now I get it: `nil` itself isn't a value. `nil` is syntactic sugar that expands into a nil value. (In other words, confusingly enough, `nil` and “nil value” are different things!) This is unlike Java, where `null` itself is a value.
It would be very helpful if people described things precisely.
> All languages have this sort of wart in them, where two or more perfectly sensible decisions interact to create something that isn't sensible at first glance.
This means that at least one of the two (or more) decisions was less sensible than it originally seemed. Good design decisions don't introduce warts into a system.
func (o *Object) ReturnSomething() int
to func ReturnSomething(o *Object) int
In the first case, it may "seem" that a nil Object would be invalid, but in the second case it's obviously valid, and makes complete sense. It may be described as a "wart", but it makes complete sense to me. The issue is, in my opinion, that people drag their own expectations into programming languages as they learn them.Also, sometimes nil is a perfectly valid value of something and can implement interfaces. You can call methods on nil receivers because method calls are just curried function applications over the value. It would be odd if the interface compared equal to nil just because I happened to implement it with a value that's valid with nil.
In this case, it's an implicit conversion from "nil" to the "nil value" of a given type. This is convenient in many cases, but causes confusion in other cases.
It's also not an implicit conversion from nil to something. Nil isn't a value the way 0 is a value of an integer or "foo" is a value of string.
Per Go spec (https://golang.org/ref/spec) nil is "predeclared identifier which has no type". That implies it doesn't have a value and therefore cannot be converted to a value.
Nil is zero value of pointer types (which in practice end up being a pointer whose value interpreted as integer is 0) and also a zero value of interface type (which is interface without a type and without a value) and a few other types.
Upvoted because of this, because it clarified my earlier confusion. That being said, I don't really agree with the rest.