4 ms·
Sure, Go is ugly. I had the same reaction as you. But it's so damn functional. There are plenty of warts, syntax and design-wise, but once you get over them, it
by lobster_johnson 14y ago
Sure, Go is ugly. I had the same reaction as you. But it's so damn functional. There are plenty of warts, syntax and design-wise, but once you get over them, it's actually a decent language.
Compared to Erlang, for example, it's positively beautiful. I like Erlang's execution model, but the unnecessarily gnarly syntax and the antique approaches to some things (no real strings, no Unicode, tuples that depend on positional values instead of named attributes, horrible stack traces, tail-call recursion as a looping construct, etc.) has made me stay away.
Go is a decent alternative to both C/C++ and Ruby for me these days. There are plenty of things I don't like about Go, but it's easy to forgive many of them when the language makes you so productive (at least for the things I need it for; it's pretty bad at web app development and completely useless for GUI development), so I do. Sometimes you just want something that works, with minimal amounts of pain. C++ works, but is always painful to me because it feels like the language is working against me, not with me.
I love the simple syntax in Go; the no-nonsense approach to object-orientation, the way the typing system allows adding methods to arbitrary types, which may have been inspired by Haskell's typeclasses. I love having native Unicode strings, first-class functions, a simple package system, built-in concurrency and decent networking in the standard libs. I love the built-in documentation generator (although it's too simplistic at this point; why not Markdown?).
Things I don't like:
* Capitalized names for visibility.
* nils in the language instead of Haskell-style Maybe.
* nil cannot be used in place of false.
* The "non-nil being nil" insanity (an interface value can be nil, but it can also be non-nil and contain a nil value).
* Functions return errors instead of Haskell-style Either monads, or Erlang-style matching. (I see the problem with exceptions, but Go's solution is worse and leads to very awkward code that has to branch a lot to catch errors.)
* The fact that "go" is a language keyword; compare with Rust's very elegant task spawning, which is part of the standard library rather than being built into the language, and yet relies on first-class language constructs to integrate perfectly.
* That "range" is not extensible (that I know; it only works on maps, arrays, slices and channels).
* The whole GOPATH thing, pretty much requiring that you maintain a local tree with symlinks.
* That "import" when used with Git cannot be pinned to a specific revision (so if you rely on a third-party package, it could break your app at any time if HEAD changes; it's ridiculous, and counter-productive, to have to fork third-party repos just because of this).
* That packages have only a single nesting level. I don't mean that I should be able to create a package "x.y.z", I mean that given a package "x", all the files have to be in the same folder. I can't organize the tree in multiple subfolders.
* That statements are not expressions.
* That semicolon elimination necessitates some insane syntax at places (like having to end a line with ",").
* The lack of structural tagging in the language (similar to Python and Java annotations), and the fact that they did add tagging, but only for struct fields, and the tags can only be strings.
Right now, Go is, in my opinion, mostly an inelegant, weirdly-shaped thing that fits into the weird hole not filled by C and C++, a stepping stone to the next big language. I don't love the language, but I love how I can do the same things I was planning to use C++ or Ruby for; as a C++ replacement I gain productivity and simplicity; as a Ruby replacement I gain performance.
Go is, if anything, a very pragmatic compromise that favours simplicity over complexity at the expense of structural and syntactical elegance. It looks a lot like Java around 1.3-1.4, before the enterprise stuff derailed its focus. My concern is that Go has no particular philosophy as a foundation; it bakes in some current concerns (concurrency, networking, ease of use) and made itself a very useful hammer for hammering today's nails, but may not be as easy to extend to work with tomorrow's screws.
PS. I, too, come from Pascal — specifically, Borland's Object Pascal. While I have fond memories of that language, I'm not sure elegance was one of its main traits.
- pjmlp 14y agoI also am a Pascal refugee, having started using it with Turbo Pascal 3.0, and most of the versions until Turbo Pascal for Windows 1.5 and a few toy projects with Delphi. What attracted me to Go initially, was Oberon's influence in the language, like the packages, method signatures, Pascal declaration way and low level tricks exposed via the unsafe package. But like yourself after a while using the language, before the 1.0 release, I came to the conclusion that I am better served with more expressive languages. So nowadays I play around with C++11, Rust and D.
- grey-area 14y agoNice list of frustrations with Go, though I wouldn't call it inelegant - the syntax may be homely, but the simplicity gives it a certain minimalist elegance. Re nils, yes this still feels pretty ad-hoc, I wonder if they'd do anything differently there now if they could? Probably there is no easy way out now they're past 1.0. It would be nice to see an extensible range and I've had this thought myself (as have others), there has been some discussion on the list, and they're not sure: https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/n1izOhyaO8I https://groups.google.com/forum/?fromgroups=#!topic/golang-n... but then you can also turn it around and iterate by passing in a function to the structure to iterate: func (self *DataStructure) Iterate(fun IteratorFunc) Re GOPATH, what do you mean here? Re packages having one level - I actually love this - if you want to nest things in folders, Go is trying to tell you to split it into sub-packages (in that opinionated manner it sometimes adopts). Of course this might feel restrictive, but if a package has lots of files I'd rather it was split up and organised into packages with clear boundaries between them rather than into an interconnected set of files/folders which only makes sense to the author of the code because it's all in one package with no boundaries. This restriction means we will see apps composed of packages by default rather than all in one namespace because it's easier. Re the versioning, they originally resisted versioning the language, but eventually gave up on that idea and used versions, so I suspect for packages they'll eventually recognise the need for this when the ecosystem of packages grows sufficiently. Versions do introduce problems of their own (dependency hell), but IMHO being able to reliably import snapshots of a package (tag, branch or version) will be essential long term without having to fork a repo and rename it just to do so. If go becomes popular you can expect this to be addressed by third parties if the go team doesn't bother. Re the tagging, in a way I'm pleased that they avoid adding lots of features like this, as this is the stort of thing I hate even in the limited version they have (on struct fields) - it's untidy and gets misused and overridden to try to extend the language (see sql libraries in Go tagging fields with all sorts of their own meta-data). Re commas on lists, this bothers me less than having to put semicolon & LF on every line, I think it's a fair trade. Re philosophy, I can't speak for the Go authors, but I've found radical simplicity to be its overriding principle, which explains some of the limitations which annoy you above and the ditching of a lot of OO baggage which languages nowadays are expected to carry whether they want it or not. I've found the simplicity worth the trade for some small frustrations.