9 ms·
> Tony Hoare apologized for inventing the null reference: I call it my billion-dollar mistake. Have we learned nothing? Many languages without NIL/Nil/nil/nul
by beeforpork 6y ago
> Tony Hoare apologized for inventing the null reference: I call it my billion-dollar mistake.
Have we learned nothing? Many languages without NIL/Nil/nil/null/NULL existed already when Golang was born.
And this attempt to heal the damage hurts, too:
> “make the zero value useful” philosophy
This is like instead of programming by exception (Java), it's programming by ignorance (of errors).
I like a few things about Golang (handling of numeric literals, for example), but not this thing.
- gameswithgo 6y agoYeah it is a strange choice, maybe just reflecting what the creators of Go are used to. They have always had null and haven't had any problems with it, why change? Null made since in the early days of C, an option type back then would have been prohibitively expensive. Today, not so, any language that can afford garbage collection, the cost of an option type is lost in the noise, and modern compilers can often optimize the cost away entirely. (though that would hurt Go's fast compile times a little bit)
- iudqnolq 6y agoRust has a zero-runtime-cost Option<T>. Presuming T is a non-nullable pointer it compiles to something that uses the nullpointer to store the None varient. (This isn't a special-case for Option in the compiler, this optimization applies to any two-varient enum where one varient can store a pointer and the other varient stores nothing).
- higerordermap 6y agoEarly C compilers were not optimising compilers. The hardware was very limited. Although I would agree it was possible to design the language much better to avoid Null, most buffer overflows etc.., C was not designed to be good from PL standpoint. It was designed to write something and then evolved.
- morelisp 6y agoEarly C compilers were non-optimizing compilers because C is among the hardest languages to optimize, not because the hardware was limited. Frances Allen described C as a "serious regression" in language design which "destroyed our ability to advance the state of the art in automatic optimization" because of how its semantics blocked most known optimizing transformations.
- masklinn 6y ago> Null made since in the early days of C, an option type back then would have been prohibitively expensive. Of course not. Option types are as old as C, and they don't cost anything more at runtime than a regular pointer, or a union tag, costs.
- mdasen 6y agoI think the idea of "useful zero values" in Go is a mistake from bias grown out of being at Google. Protocol Buffers implement default zero values (https://developers.google.com/protocol-buffers/docs/proto3#default https://developers.google.com/protocol-buffers/docs/proto3#d...) and there's no way of discerning whether something is "false" or "unset", the empty-string or unset, etc. In that context, it makes perfect sense for Go to have similar behaviors for zero values. In some respects, you can get around this by simply adding another field. You can have `bool over18; bool over18IsSet` and I'm guessing that Google's internal usage of protobufs does this. In a certain way, even getting rid of null/default values doesn't fix all problems when it comes to things like updating data. Think about updating a record where a field could be set or unset - let's say a person's age could be a number or empty. If I want to send a request updating their name, maybe I send `{"name": "Brian"}` because I don't want to update the other fields. How do I unset Brian's age? `{"age": null}` makes some sense, but a Java (and many other language) deserializer will have null for age with `{"name": "Brian"}` too. I mean, the age field has to be set to something in the Java object. You could manually read the JSON, but that's janky and brittle - and hard in terms of interoperability with libraries and languages. Maybe Google's protobuf designers would argue, "you really need to have explicitness around your values and forcing defaults means forcing engineers to deal with things explicitly." I don't think I agree with that. I don't like Go's nulls and default values. I think most languages are moving away from that kind of behavior with other new languages like Kotlin and Rust going against it and older languages like C#, Java, and Dart trying to bolt on some null-safety (Java via the `Optional` object and C# and Dart via the opt-in `TypeName?` similar to Kotlin). It's possible that this is a wrong direction chosen by many languages. We've seen bad programming language fads before. In this case, I think we're on the right track and Go's on the less-great side. Go has a lot to like, but this is one of those odd decisions. I understand why they did it. Go comes from Google where Protocol Buffers have similar default-value behavior. I think Go would be better if it had made some different decisions in this area.
- cle 6y agoThe only apt comparison IMO is Rust, the other languages with JIT compiling runtimes aren't really useful comparisons. To me this looks like a discussion about syntax and ergonomics. Go provides the same mechanisms: * for safe dereferencing, use "val, ok := *valRef" * for potentially-unsafe dereferencing, use "val := *valRef" Every language in that list has equivalent mechanisms. In Rust you can use one of these methods: https://doc.rust-lang.org/std/option/enum.Option.html https://doc.rust-lang.org/std/option/enum.Option.html or pattern matching. That's a whole lot to pick from. But Rust also makes it more complicated to reason about your memory, see for example https://doc.rust-lang.org/std/option/#representation https://doc.rust-lang.org/std/option/#representation So, given Go's design tenets, using pointers makes a lot of sense to me. It is easy to reason about them in terms of memory and resource consumption, there are only a few ways they can be used, pass-by-value semantics further reduces the centrality of them, and they don't require a JIT compiler to be efficient.
- kgeist 6y agoIf they required values to always be initialized, that would either require a concept of constructors (the whole OOP thing they tried to avoid), or require all struct fields to always be explicitly initialized at every instantation (which can get awkward), or allow specify default field values (which sounds like implicit magic Go tries to avoid too). In Go, by-value semantics is more common than in Java with its mostly by-ref semantics, so nil is less of an issue. It's also easier to implement (the allocator already memsets to zero for safety) So it's just a combination of factors, they took a bunch of shortcuts. Not defending it, but their choice makes sense, too.
- dgellow 6y agoMy experience writing Go is that nil pointer expectations are really not that big of a problem in practice. Linters and unit tests are quite good at catching those.
- stouset 6y agoOne can say that about literally any language with nil/null, and it's been empirically demonstrated beyond reasonable doubt at this point. The reality is that you don't know where your nil-dereference bugs exist because your language doesn't detect and force you to eliminate them.
- dgellow 6y agoA nil-dereference is very easy to spot in production: you have a panic and a stack trace in your logs. Which means you can check after a few years how many nil-pointer exceptions you got in your actual system. In my experience that numbers is really low.
- yawaramin 6y ago> very easy to spot in production: you have a panic and a stack trace in your logs. Not a great experience for your users though. And definitely not great for developers who get paged to handle these production incidents that could have been caught at compile time.
- baby 6y agoMy experience is that any Golang codebase that makes use of protobuf ends up having DoS vulnerabilities (because they forget to check for nil somewhere).
- ben509 6y agoI think nil/null is a symptom of the real issue: the language permits partially constructed data types, so it has to assign something. That's a consequence of the "always mutable" model whereby the responsibility of initialization can be shared by the object constructor and the caller. But there are many cases where it's very intuitive for the caller to set up an object, especially in the objects as actors model. I think to make that work, you'd want to track the evolution of the object's state, especially noting when all fields have defined values.
- frenchy 6y agoFor what it's worth, it's more ceremony, but you can work fine with partially constructed data types without null, it's just that the nature of their construction either needs to encoded int the types directly, or they need to be initially constructed with defaults and you need to decide if you want them to explode/panic if they're not completed, or just return potentially unexpected defaults. I've seen all these approaches in Rust.
- higerordermap 6y agoI don't think mutability is problem here. Many imperative languages don't have null.
- masklinn 6y ago> That's a consequence of the "always mutable" model whereby the responsibility of initialization can be shared by the object constructor and the caller. It's not though. An "always mutable" model can require that objects be fully initialised up-front. Rust does exactly that.
- rowanG077 6y agoWell Go's goal is a lowest common denominator language with the least amount of features possible and the easiest to learn for new graduates. This essentially makes it almost a toy language in fancy clothes. A toy language with the money of google backing it so it does actually feel useable.
- kccqzy 6y ago> the easiest to learn for new graduates And I'd say it fails at that goal, judging by the number of gotchas in fundamental concepts of the language like slices or interfaces. A surprising behavior of slices that had discussions on HN, and something I discovered in my own code as well: https://news.ycombinator.com/item?id=9555472 https://news.ycombinator.com/item?id=9555472 And of course this gem was on HN just yesterday: https://news.ycombinator.com/item?id=26631116 https://news.ycombinator.com/item?id=26631116
- sugarkjube 6y ago> easiest to learn for new graduates This was never a goal of go. Go was conceived out of frustration with c++. They wanted to reduce language complexity and build times (among other things). For me personally it's C without the hassle.
- rowanG077 6y agoThis is false. Here it is straight from the creator of the language: https://www.youtube.com/watch?v=uwajp0g-bY4 https://www.youtube.com/watch?v=uwajp0g-bY4
- cmrdporcupine 6y ago"Not capable of understanding a brilliant language." Wow as a googler I find this... Awful.
- sullyj3 6y agoMan, people are really downvoting accurate information just because the truth hurts.
- brundolf 6y agoI had to do a double-take; Rust, one of the languages leading the mainstream away from nullables, was created by Graydon Hoare (I looked it up and there's no relation to Tony) But yeah: I once heard Go described as "a C fan-fiction". It was designed by and for people who use and like C, and just wanted some niceties built on top of it for their usecase of writing distributed systems (garbage collection, strings, easy networking and multithreading, easy cross-platform builds, very basic polymorphism). It was not designed by people who were interested in stepping back and re-evaluating the big picture beyond those practical necessities I see it as C++ (literally, "C improved"), for the modern world (instead of the 80s). For all the good and bad that implies.
- masklinn 6y ago> But yeah: I once heard Go described as "a C fan-fiction". It's more of an alt-java than a C fan-fiction. Most of the stuff people are interested in in C, Go dropped. However while Go clearly disagreed with Java on the specific means and most important bits the core goals and aesthetics are extremely strongly reminiscent of Java's.
- ameixaseca 6y ago> Have we learned nothing? I suppose not, if you are considering "we" as "the set of people that designed languages like Go or justify the design decisions made by such group". If you are considering "we" as humanity, in general, I'd say that no, "we" actually learned a lot and "we" already know better. But you still have some building rockets to try to prove the earth is flat, unfortunately.