4 ms·
Safe as in nil not even being equal to nil any more, I know I'll sleep better.
by andreasgonewild 9y ago
Safe as in nil not even being equal to nil any more, I know I'll sleep better.
- weberc2 9y agonil is always equal to nil. You might be confusing it with comparing a nil pointer to a pointer to a nil pointer, which are not equal.
- andreasgonewild 9y agoI don't care what we call it, it's still confusing as hell.
- weberc2 9y agoYeah, indirection can be confusing to new programmers, but its absolutely fundamental, so it's better to get used to it than to complain about it.
- andreasgonewild 9y agoExcept I have 32 years of daily practice and plenty of experience from most paradigms/languages/kinds of software out there. I'm guessing similar goes for some of the hundreds of people who complain about the same thing. This attitude is exactly why many choose to stay away from Go and its community. The constant denial of any problems and claims that everyone else got it wrong. I don't know where it started, most probably Pike & co; but its not very constructive.
- weberc2 9y agoIf you think that's my attitude, you don't know me. I have lots of criticism for the language, but pretending a pointer isn't a pointer isn't the solution to people not understanding indirection.
- lobster_johnson 9y agoThe nil-interface wart actually does result in comparison issues, and it's something that trips people up all the time: package main import ( "fmt" "io" ) type Thing struct{} func (t *Thing) Close() error { return nil } func main() { var x *Thing var y io.Closer = x fmt.Printf("x == nil -> %#v\n", x == nil) // true fmt.Printf("y == nil -> %#v\n", y == nil) // false } Here, both x and y are conceptually nil, but y cannot be compared to nil. Go is a strict language, but it's curiously lax about many things, including this. "go vet" won't even warn you that you're unintentionally wrapping nil in an interface. This goes way beyond just a trivial example like the above one, though: Any general-purpose code that has to deal with arbitrary interface{} values can't just check for nils, but need to do things like this: func UnwrapReflectValue(v reflect.Value) interface{} { if !v.IsValid() { return nil } if v.IsNil() { return nil } if v.Kind() == reflect.Ptr { v = v.Elem() if v.IsNil() { return nil } } if v.Kind() == reflect.Interface { v = v.Elem() } return v.Interface() } I don't know why Go doesn't let "y == nil" return true here; boxed values are supposed to have the same high-level semantics as unboxed ones, and off the top of my head I can't think of any code where changing the current behaviour would cause breakage.
- weberc2 9y agoYour mental model for an interface is incorrect--an interface is just a pointer. A pointer can be nil, but some pointers point to other nillable types. If we paper over this for nil checks, we destroy states that are semantically valid/important. Abstracting as you propose creates more surprising behavior than it fixes. On the other hand, all it takes to avoid the problem altogether is the understanding that interfaces are just (fat) pointers.
- lobster_johnson 9y agoMy mental model is just fine, thanks; I've written about 70k lines of Go, and I'm perfectly aware of how it works. I'm saying it's a misfeature. interface{} is a leaky abstraction.