7 ms·
These points are all very true, and I admit I haven't done more with Go yet than play around. But there are a few reasons I feel I don't like Go, or at least, t
by graue 14y ago
These points are all very true, and I admit I haven't done more with Go yet than play around. But there are a few reasons I feel I don't like Go, or at least, there are warts that will probably limit how much I'm going to like it.
Nil pointers are #1 on that list. Tony Hoare called them a "billion dollar mistake"[1]. In Go, as in C, C++, or Java, any pointer can be `nil` (similar to `NULL`) at any point in time. You essentially always have to check; you're constantly just one pointer dereference away from blowing up the program. Since ways of solving this problem are known, I find this hard to swallow in a new language.
Compare Rust where, unless you have explicitly used the unsafe features of the language, all pointers are guaranteed non-nil and valid. Instead of a function returning a nil pointer, it returns an `Option` type which is either `Some ptr` or `None`. The type system guarantees you have considered both possibilities so there's no such thing as a runtime null pointer dereference. Scala has a similar `Option` type, as does Haskell, calling it `Maybe`. In 2013 I don't want to still constantly check for a nil pointer, or have my program blow up at runtime if I forget.
The second disappointment is that when I looked into it, it seemed there are ways to call C functions from Go code, but no working way to call Go from C code. Maybe that wasn't a goal at Google, but it seems like a missed opportunity. As a result, you can't use Go to write an Nginx module, or an audio plugin for a C/C++ host app, or a library that can be used from multiple languages.
I think there is a real unmet need for a higher-level, safer language you can use to write libraries. Imagine if zlib, or libpng, or the reference implementations of codecs (Vorbis, Opus, VP8) could be written in something like Go. Or spelling correction libraries. Currently we have two tiers of libraries: those written in C/C++, which can be used from any language under the sun (Python bindings, Ruby bindings, Perl bindings, PHP bindings...), and those written in high-level dynamic languages (Python, Ruby, Perl, PHP, ...) which can only be used by the same language. We need a middle ground. C isn't expressive or safe enough to deserve to be the lingua franca like this. And Go is tantalizingly close to replacing it, but not quite.
[1]: http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake http://qconlondon.com/london-2009/presentation/Null+Referenc...
- pixie_ 14y agoWhat about instead of having non-nullable types - do what objective-c does and 'drop' calls to null objects. There's been a number of times that instead of my application blowing up from a null exception, whatever feature my user was using just didn't work, but the rest of the application ran fine and they could report the bug to me. It's a much nicer user experience to have the car 'not' blow up if the AC button isn't working.
- halter73 14y agoI think that in the case of unforeseen error in an application, the program should blow up instead of dropping calls to null objects and continuing on as if nothing has gone wrong. I would not want to work on code that relies on this type of behavior since it would be so easy to overlook. Every time an object gets deferenced I would have to consider that it might no-op and consider how that might affect the rest of the program's execution. If you really want to 'drop' calls to null objects, be explicit about it and only make the call inside of a conditional that checks that the object is not null. Your fellow programmers will thank you. Most of the time it is much better that a program crashes instead of silently operating under incorrect assumptions. This is particularly true if the software is doing something critical. But even if it's a casual game, do you want to risk corrupting your costumers' saves? The following blog post makes basically the same argument, but not about null pointers specifically: http://www.codinghorror.com/blog/2007/08/whats-worse-than-crashing.html http://www.codinghorror.com/blog/2007/08/whats-worse-than-cr...
- KMag 14y agoThere are very few problem domains where "do something, even if it's the wrong thing" is better than refusing to run. Perl and PHP have both rightly been criticized for this sort of thinking. I write automated trading software. If I created a bug, I'd much prefer my program just stop working rather than no-op out a hedging routine or no-op out a regulatory compliance routine. There are also plenty of safety-critical applications where a machine would be perfectly safe if it just stopped working, but would kill someone if it no-opped out a routine. I could see a photo hosting site accidentally giving people without accounts access to everyone's private photos because a filtering routine got no-opped out. I'll grant you that there are a few small domains where this would be desirable behavior, but I think if it's that much of an advantage, those domains should have domain-specific languages. Skipping method calls on null objects is a terrible feature for a general purpose programming language.
- meaty 14y agoThis. One of the most important things I've learned over the years is fail early and verbosely. My code is always littered with pre and post condition checks. As a side effect, we discover 99%+ of bugs before production every time.
- pekk 14y agoI don't know that this is 100% a problem with the language, which cannot be reasonably coped with. Is it an option to write your own code so that it does not return nil pointers, and only check when you are interfacing which code which might not give you the same courtesy? In other words - in order to avoid driving yourself crazy with paranoid checks everywhere (whether they are done by the runtime or by you) maybe you can defend the invariants at the 'perimeter'. For that matter, there are going to be many places in many projects where nil pointers are going to be exceptional enough that it is OK to shut down when they occur. There's not always a need to check and handle at points where will be a rare event and not such a big deal when it does happen. It isn't necessarily a virtue for a program to keep on running when its contracts can't really be fulfilled any more due to the funkiness of its environment or dependencies, so sometimes the best way to handle an error is to just stop and give debug info rather than checking and handling. I completely agree that it is a huge missed opportunity not to be able to call into Go from C code and I can understand complaints that mandatory gc might prevent Go from replacing C in some domains.
- mdwrigh2 14y ago> I completely agree that it is a huge missed opportunity not to be able to call into Go from C code and I can understand complaints that mandatory gc might prevent Go from replacing C in some domains. As rsc has pointed out a few times, this problem is just a matter of someone doing the work to make it happen, not a fundamental limitation of the language itself.
- waps 14y agoYes, it just means a human needs to go in and do it. And preferably a few other humans need to go in and check it ... The real question is whether this is still acceptable for computer languages.
- coldtea 14y ago>As rsc has pointed out a few times, this problem is just a matter of someone doing the work to make it happen, not a fundamental limitation of the language itself. Yes, but as neither he nor any other Go designer went ahead and did it the problem exists.
- dscrd 14y ago"Compare Rust where, unless you have explicitly used the unsafe features of the language, all pointers are guaranteed non-nil and valid. Instead of a function returning a nil pointer, it returns an `Option` type which is either `Some ptr` or `None`. The type system guarantees you have considered both possibilities so there's no such thing as a runtime null pointer dereference. Scala has a similar `Option` type, as does Haskell, calling it `Maybe`. In 2013 I don't want to still constantly check for a nil pointer, or have my program blow up at runtime if I forget." So how is nil checking different from when I write a function that pattern matches against a Maybe in a way that I only match against the "Just" case?
- abhinavg 14y agoI believe graue was referring to the case when you are not using such a type in the code; then you have a guarantee that the value is non-null. The purpose of the Some/Option/Maybe types then becomes to indicate when a value can be null, but outside that wrapper type it is guaranteed to be non-null. So code where it must always be non-null does not have to confirm that that's the case. I think it is less about efficiency and more about not having to worry about it.
- alecbenzer 14y agoGuess: the compiler knows you forgot to check the "Nothing" case and will tell you.
- dscrd 14y agoAh, I see. I was confused by Haskell not doing that by default... at least the last time I wrote code on it. Is there actual data that says that null pointers are actually causing bugs in production software? I always thought they are just a symptom of lazy programmers, and no language can fully protect against that. Witness my awesome Haskell snippet of code: foo (Just x) = x+2 foo Nothing = undefined Ok, so it's somewhat better since the lazyness is now explicit and cannot happen so accidentally.
- friendly_chap 14y ago
- 0xABADC0DA 14y ago> Compare Rust where, unless you have explicitly used the unsafe features of the language, all pointers are guaranteed non-nil and valid. .... The type system guarantees you have considered both possibilities so there's no such thing as a runtime null pointer dereference. On the other hand, you end up with deeply nested code and it is hard to follow. I did some grepping on clang and rustc, and in clang the rate of blocks within other blocks decreases (the deeper the nested block, the less chance of it having a sub-block in it). In rustc the rate is constant, no matter how deep the nesting you have the same rate of having sub-blocks. Not having NULL and using pattern matching can eliminate NULL pointer exceptions, but the cost is code that is harder to read. The memory ownership in Rust is great, but I doubt it will ever be popular by common folk due to this ML stuff.
- danieldk 14y agoNil pointers are #1 on that list. Tony Hoare called them a "billion dollar mistake"[1]. In fact, Go made nil pointers even worse, since nil may not be nil: http://play.golang.org/p/fIde3QZt9m http://play.golang.org/p/fIde3QZt9m Every interface is stored as a tuple of a type (pointer) and a value (pointer). The interface tuple returned by a() is ([]int, nil), comparing this to nil, which is a (nil,nil) returns false(!). So, Go doesn't only have null pointers, it has null-pointers which sometimes has a 'hidden' type, which does not compare to the literal nil.
- deleted 14y ago[deleted]
- vanderZwan 14y ago> The interface tuple returned by a() is ([]int, nil), comparing this to nil, which is a (nil,nil) returns false(!) It's certainly a subtlety that can bite you, but I'd say that in this form it is arguably more consistent: assigning a type to an interface and having that be nil is not the same as assigning nil to an interface - those two variables are not equal and should be treated as such.
- blablabla123 14y agoHow is this more consistent? This can produce nil pointer dereferences.
- vanderZwan 14y ago> those two variables are not equal and should be treated as such. In that sense. Don't get me wrong: I'm not saying it fixes other problems with nill pointers, and yes, it introduces an extra possibility for dereference problems. Just like you're allowed to call methods on nill pointers if it's a nill pointer to a type that has these methods. https://groups.google.com/forum/?fromgroups=#!searchin/golang-nuts/calling$20methods/golang-nuts/wcrZ3P1zeAk/WI88iQgFMvwJ https://groups.google.com/forum/?fromgroups=#!searchin/golan...
- blablabla123 14y ago
- justincormack 14y agoLua is easily callable from C as well as the other way round. But you are right it is not common for high level languages.
- graue 14y agoInteresting. Are you aware of any libraries taking this approach (write a library in Lua, create bindings for C, C++, Python, Ruby, etc)?
- justincormack 14y agoOne I saw recently http://lua-users.org/lists/lua-l/2012-12/msg00818.html http://lua-users.org/lists/lua-l/2012-12/msg00818.html