Zef writes this as if it's completely amazing that people are leaving Node for Go. Node is based on JavaScript. There are arguably more things wrong with JavaScript than with any other popular programming language, as evidenced by book titles like "JavaScript, the good parts". This is common knowledge; we're all trying to do good work despite JavaScript, seldom because of it. So Node: it's fast, we can share code with the browser, but it's a bitch to use. We knew that when we signed up.
Conversely, Python is a great language but it's not as easy to make it go fast. It's slow, but it's great to use. We also knew that when we signed up.
It's great that Go is getting more mainstream adoption! Deservedly so. But it's probably still easier to be super-productive developing a CRUD app in Ruby or Python. And it's still easier to share code between backends and web frontends with Node. If you don't need either of that, and you do need performance, then, yes, maybe you shouldn't pick Python or Node.
I agree that Go is a great option to consider, but Zef is framing it a little as a silver bullet, and well, of course it isn't.
What part of the article did you read as "Go is a silver bullet? I read it as a list of articles about people/companies who are switching to Go with each giving their reasons for adoption.
No part in particular - I don't disagree with Zef or the people he quotes. But the entire article does have this "look, all these smart and influential people are ditching $THING for Go, you should too!" feel to it. They're ditching stuff for Go for the particular kinds of problems that Go is good at. This is a subtle but important distinction that Zef isn't making, so I figured it was a useful addition to the debate.
The one big substantive point was about callback hell. Coroutines and channels are exactly what's needed to solve that. Add in a minimalist language design focus on programming in the large, and you have a prescription for what ails Javascript on large projects.
This doesn't make Go a silver bullet. (So don't make that mistake, please!) It just happens to be the right kind of tool for two of the more salient problems right now.
I agree that callback hell sucks, and promises are a vast improvement, but still shitty. Coroutines and channels are not obviously 'just what's needed' in my opinion however.
I think they're part of a larger picture. Mature languages should have multiple concurrency models available for different tasks. Clojure, for instance, supports coroutines, threads, and multiple other flavors of concurrent programming.
There is no silver bullet, polyglot concurrency is the future most likely.
One kind of "polyglot concurrency" was the precisely problem of the past! In fact Rich Hickey says himself: You can do concurrency in Java with semaphores and such, but you end up doing some sentinel-thing that's somewhat specialized for your particular subsystem. Then you have to interface with this other subsystem...implement this new feature...then several months later you have a bug introduced because these weren't put together correctly.
In a large Clojure project, you should pick a particular way of doing things, then maybe allow a wrinkle or two, then be consistent about it throughout your project, or at least in that subsystem. Maybe you make your entire model an Atom and have a few FIFO queues for information coming in and going out? What you don't want to do then is to mix in transactional memory or Agents. Otherwise you can find yourself back in the "polyglot" mode of Java. With Go, you have a few flexible primitives from which to produce concurrent systems, but the same thing goes here too. You need to pick a few patterns and stick with them. Otherwise you can make your life much harder.
However, when you start going parallel, whatever you have chosen can go pear-shaped for some hard to fathom reason. Go is no better in this regard.
Agreed that you shouldn't mix concurrency models excessively, but many problems do call for a mix. I don't think Rich was referring to what I am. He was talking about the trouble composing Java concurrency using locks and such, which is just hard.
On the other hand with clojure, a standard mix is to use non blocking IO to multiplex a large number of connections, then delegate work to a threadpool (using clojure refs/atoms etc.). Such a system has a much smaller chance of deadlocks and other issues.
A great example of polyglot concurrency is the clojure reducers framework that lets you delegate work to a fork/join pool. Most people don't need it, but it's nice to have a safe, seamless interface to such an advanced concurrency tool.
> There are minor details wrong with JavaScript. Normally you don't encounter them in daily use.
If you really believe that, I can only assume that you either don't have very much experience with Javascript and haven't yet been burned (or haven't yet discovered that you've already been burned), or that you don't have any experience outside of Javascript and therefore are not aware that languages exist that have all the niceness of Javascript but almost none of the bad stuff. I say this as someone who is primarily a Javascript developer professionally.
Yes, there are languages that are worse than Javascript to work in (I'm looking at you Java and PHP), but there are many that are much better. It's worth noting that everything that is good about Javascript already existed in other languages before Javascript got invented. In fact Brendan Eich has stated that his intention was to create Scheme for the browser. If only he had just used Scheme as it existed, things would have been so much better!
> Yes, there are languages that are worse than Javascript to work in (I'm looking at you Java and PHP)
Java has an enormous ecosystem, is fast, is stable, has static typing, has more tooling than anything else, is easier to learn, does not have all the gotchas that Javascript has. I don't consider Java a worse language at all.
I use Java since a decade, and frankly I don't understand that rage against it while it is a totally valid option to start a project with, even a startup. If you want to get RESTful and all there's everything you need, etc.
Take it from a guy doing some Golang since more than one year and enjoying it a lot, also well versed in Python, Javascript, and even OCaml.
In fact, the time it took me to write this comment, I decided that I don't care anymore. Use what you need for the job and be prepared to change when something new is out and have a real impact on what you do.
I agree that Java has relatively few WTF-level language design flaws. So on that count it wins against Javascript. But Java also doesn't have the expressive power of Javascript that comes from having 1st-order functions. Static typing is nice in principle, but the verbosity of Java's type system makes programming in Java feel like running in wet cement. I respect that there is a humongous ecosystem surrounding Java, but that doesn't really speak to whether the language is pleasant to work with or not.
Static typing is nice in principle, but the verbosity of Java's type system makes programming in Java feel like running in wet cement.
So then programming in Java with a powerful IDE is like running in wet cement with bionic stilts? I think this is actually an apt analogy, especially for when things don't work quite right or when things get a bit laggy.
I've been working with JS professionally for the last 3 years...priorto that, spent many years with C++/SQL/etc...the statements that people get "burned" by JS (pesumably because of the weird coercion or floating-point comparisons?) I've never understood...maybe I just write my code in a weird way that insulates me from those things...I've never experienced more than a "minor surprise" in dev - certainly never been "burned".
> maybe I just write my code in a weird way that insulates me from those things
Maybe you do. I certainly strive to. But don't you sometimes have to work with other people's code too? I recently inherited a 10 years old codebase written by people who had not heard of implied global and didn't use the var keyword.
In my previous job I had to educate several frontend developers about the dangers of using parseInt without a radix parameter. The ones that already knew did so because… you've guessed it: They had previously gotten burned.
I worked on a project in which the backend had a rest API that served json data. Among the data were some rather long integer IDs. But since javascript doesn't have integers but only floats (of all things), the IDs got rounded off in weird ways. Not very useful as IDs after that! If all everyone ever used was javascript, this would perhaps not have surprised anyone, and it would be known by all that you shouldn't use a Number as an ID, but always only Strings. The problem is that most back-end developers are not Javascript experts and in their world it is only natural that you should be able to use a number as an ID (as it should be IMO).
As time goes by and you get experienced, you begin to learn all of these little 'quirks' of the language, and maybe you start to adopt a defensive style of programming that insulates you from the worst of them. And if you've never experienced anything else, it's easy to tell yourself that this is just the way things are, and that it's probably the same for everyone. But I'm here to tell you, that this is not the case! Sure, other (better) languages have surprising behaviours too, but they are mostly good surprises that empower instead of restrict.
> But don't you sometimes have to work with other people's code too?
Yes, I suppose I have gotten "burned" by other people's JS quite a bit...but not any more than I've been burned by other people's bad SQL or C++ or C#, to be honest.
> Sure, other (better) languages have surprising behaviours too, but they are mostly good surprises that empower instead of restrict.
I am assuming that by "better" languages you are meaning type-safe ones... I know this is not a popular opinion, but I honestly just prefer dynamic typing. When I code, there is only room for one whiny child in the equation: me. Not the language I code in. I would rather not have my language throw a temper-tantrum and break down because I gave it something a millimeter different than what it was expecting. If the object is supposed to have "thing" and it has "thing" then shut your mouth and use it, language. Where JS gets weird is that it tends to put "thing" there in some cases where you didn't expect it, but honsetly after learning the few cases where it does that, I've never had a huge problem with it - I think, like everyone, I bumped into some mild surprises (ya the radix thing with parseInt and [] == false and soforth), but they were never more than just mild surprises in development. I know it drives people insane - and some people will swear that there is no way to build large systems with it. I suspect those people are the same ones who asked the teacher for extra homework for the whole class when they were kids. That was just never me, and I would just respectfully disagree. To me JS is just a ton of fun and there are too many people making too many awesome things with it to ignore. Apparently TJ got tired of it - maybe I will one day, too.
Until then, I just wish people would recognize that the reason JS "won" the language wars of the mid-late aughts was specifically because of the "get-out-of-the-way-and-let-coders-code" dynamic built into it - IMHO the modern web could not have been built with anything else. If you have any recos for "better" languages that share that dynamic, I would be very interested in hearing them.
How do you "get burnt" by parseInt without radix? Yes, I made that mistake before, too. But it's usually in a situation where you detect your error immediately. Then I add the radix, problem solved.
I don't know the libraries of other programming languages by heart either. I would be making lots of mistakes in other languages if I wouldn't look up the correct API all the time.
It's probably because c++ is arguably even worse (harder, with speed advantage to be fair). I haven't seen anything worse than MFC/boost 300 level underscore filled template stack trace, in any language.
> In fact Brendan Eich has stated that his intention was to create Scheme for the browser
No. Read https://brendaneich.com/2008/04/popularity/. "Come to Netscape, do Scheme in the browser!" was the bait. When I got to Netscape, it "had to look like Java". And given timing both internal and due to MS coming after Netscape, it had to be done really, really quickly.
> Python falls through because it doesn't have real lambda.
No it doesn't. Been using it for about 10 years can't remember being bothered by lacks of "real lambdas"
> There are minor details wrong with JavaScript. Normally you don't encounter them in daily use.
If there would be minor detail we wouldn't have had the "Good Parts" book. And trying to deals with variables in Javascript is pain, var vs no var, what does this do. Really strange weak typing rules.
Adding [] to {} should not produce some random value (what is it NaN or Object), it should throw an exception.
I assume you're referring to the "Wat" talk by Gary Bernhardt, here.
My question is why does it matter? It's funny and notable behavior, but why is this a problem that a real programmer will face dealing with a real problem?
If you normally only do a couple lines of jQuery per day then I agree that you don't encounter the warts very often.
If however you want to do even some OOP you cannot miss the world of hurt that is coming your way. Then there's the horrible weak type system which makes maintenance of anything needlessly complex, not to mention the global variables, unused reserved words, anything that has to with numbers etc.
As already stated, it depends on what you're doing. I have to calculate lots of numerical things, javascript isn't brilliant for that at all (I'm not against js, I was an early advocate and have used it for years).
Python doesn't have real lambda, who cares? That may or may not matter to you, it mostly doesn't matter for me, most of the time.
You've directly commented on a post about how understanding the context in which you use your tools is the crucial factor by totally ignoring the point.
Doubles do have 53 bits of int precision at least. Did you know libcurl uses doubles to represent file sizes? File sizes that are always integral? Don't ask me why they did that, guess it had better platform support than int64's a hundred years ago.
> Python falls through because it doesn't have real lambda.
True. What it does have though is real closures. Local function definitions with a proper name, capturing lexical state, usable as first class objects. This is a usable replacement for real lambdas, in much the same way functions are used as a replacement for just about everything in Javascript.
There are so many things in Python that have real syntax and language support, and that are lambdas upon lambdas upon lambdas in Javascript.
Carefully configured Flask can get up to 1/3rd the speed of other web frameworks. But misconfigure it, use an ORM, or if you're on django, you're serving 1/10th as many requests/sec with significantly higher latency than other languages.
Template rendering takes an appreciable amount of time. I had to replace django's (slow as shit) stock templates with jinja2 on a project because it was taking tens of seconds to render a very large page. Jinja is far faster, but it's still slow enough that I had to add a caching layer to a website that shouldn't need one.
3. Numerical shit
I implemented a video processing algorithm from a paper for a computer vision class. Python's scientific and numeric libraries were sick and made prototyping delightfully easy--then the final runs on the full dataset took forever. What I re-implemented in C++ was >10x faster. Vectorization and other tweaks can make python numerics go faster, but it's a pain in the ass. One of the goals of the Julia scientific programming language is to make loops fast enough that code doesn't have to be manually vectorized.
I work on bare bones low latency systems. Read from a socket->do some basic work->send on a socket.
I prototype in python and use zeromq so i can simply insert a new piece of code in c++ when the time is right. Throughput generally increases 10x or more for the same algorithm
Yeah, there are tradeoffs. SqlAlchemy is by far the most pleasant and thorough ORM to work with, for example. For any language. Full transactional support + every other feature you can dream of.
So, is that bad? Are my systems inferior because they are not "webscale" or "computational pipelines"? I never said I did that. Python is fast enough for what we do.
> Not looking at Go yet? It may be a good time to do so now — everybody else is.
That's going to be a large albatross around Go's neck, as it has been around node.js', and Rails before that. Large amounts of developers flocking to a new thing because "this is the thing to use now and if you don't you're dead meat".
Personally, I thought Node.js was a terrible platform for serving dynamic web sites. It is, however, a great platform if you need to make a reasonably performant general server with minimal effort (such as a message broker for example).
Likewise, people will now order their projects in Go whether it makes sense given the requirements or not. 20 years of Go experience will be needed on CVs. And when Go inevitably fails at certain things, "everybody" will move to the next thing - probably Rust, thereby completing the migration away from dynamic scripting.
> That's going to be a large albatross around Go's neck, as it has been around node.js', and Rails before that. Large amounts of developers flocking to a new thing because "this is the thing to use now and if you don't you're dead meat".
TJ's blog post is basically like if DHH ditched Ruby/Rails for Go.
> Personally, I thought Node.js was a terrible platform for serving dynamic web sites. It is, however, a great platform if you need to make a reasonably performant general server with minimal effort (such as a message broker for example).
Totally agree with you,nodejs is not a silver bullet.
> "this is the thing to use now and if you don't you're dead meat".
And not just because you'd be unfashionable, but because a lot of crucial libraries in these ecosystems will loose maintainers. The Node guy said the other day that (out of his hundreds of libraries) "Koa is the one project I’ll continue to maintain".
If I had any of his packages in production I would be terrified. The fact that he (and other "Node guys") are driving the hype train to Go tells me that I should stay as far from it as possible.
True, I think you're expected to follow the cool people to wherever they go next ;)
Maybe some ecosystems are much more about the people leading them than they are about the technology behind them. And while this is not something I'd be interested in as a developer, I understand how there could be huge benefits in that kind of lifestyle. I imagine that's a very supportive, creative, and active community to be in.
Looking at some (mis-)uses of Node, maybe that's been the rationale behind some of these frameworks all along. And indeed the first image on the page is of a marching band...
> Large amounts of developers flocking to a new thing because "this is the thing to use now and if you don't you're dead meat".
Well "why did you pick this technology?" question is a good way to find out who are you talking to. If they say "webscale" and "callbacks are this new concurrency paradigm" then well, I might not form the best opinion about them.
It's like everyone looking at everyone else's fashion sense and then quickly getting down the shops to buy up the same sort of stuff.
I suppose it depends on what you are trying to do - if it is looking good to those with fashion sense - better get down them shops. If it's to like, actually build stuff - the feeling of being uncool because of what language you use is a massive distraction to ignore.
I've been learning Go because its a great language for concurrent server systems (and better than node in some areas).
That I feel slightly cooler because of that choice feels a bit like having the right daps (sneakers) at school.
"In the past week I’ve rewritten a relatively large distributed system in Go"
Maybe I don't have any programming talent at all, but I cannot even imagine to rewrite a 'large distributed system' in a week. The not-too-large distributed systems I worked with had years of thinking behind them, I could not even type in the characters of the code in a week.
What am I supposed to take away from these links, other than the technical culture's self-defeating tendency to lionize individuals to fit a hero narrative?
If you read the second link, it's presented that that guy is actually a group of people working under a phony name, to give the cult a "hero". Drum up hype, etc.
Nicolas Bourbaki is the collective pseudonym under which a group of (mainly French) 20th-century mathematicians wrote a series of books presenting an exposition of modern advanced mathematics, beginning in 1935. With the goal of founding all of mathematics on set theory, the group strove for rigour and generality. Their work led to the discovery of several concepts and terminologies still discussed.
It is a rather vauge statement and could have used some clarification; however Go does make writing network protocols very simple, and building something like a gossip protocol based system with a leader election system is doable in a week. Even quicker if you use some of the existing distributed systems libraries for Go.
All of the HTTP, socket, encryption, compression etc libraries have a really clean, consistent design based around stackable reader and writer interfaces. This makes it really easy to combine things, swap out transport layers etc.
Go routines and channels are also nice for handling concurrent requests though I find myself using mutexes more than channels for finer grained control.
Go makes it straightforward to have one program efficiently communicating with many different servers and clients. It does this by having all network IO be event-based in such a way that it's effectively tied directly into the scheduler, and then communicating between the different goroutines managing all these connections is very easy.
I've often heard that Go founder were surprised that Go seemed to replace python more than C++ or C which were the initial targets.
By judging from the given examples it seems that it isn't the case : people seem to come to Go when they start looking for performance. Instead of writing C modules and using them from python, they just switch everything to Go.
I'd be curious to know how many start ups prototype their first software version with Go.
Note : as a coder that writes a lot of python, seing dropbox switch to Go in parallel to python so often having toxic discussions about python 3 vs 2 is really painful.
It's not surprising that people motivated by performance would arrive to Go from languages that are slower. C/C++ developers would certainly not use that argument in favour of a switch given that matching C/C++ performance is a non goal for Go.
There are other reasons C++ developers might have to switch to Go; that's what Rob Pike was referring to when he said that he was surprised that Go wouldn't replace C++. He didn't mean that Go failed to replace C/C++ as the target of optimization from slower languages, but failed to replace C/C++ for those who were already using it.
Go has been explicitly designed to avoid the perceived pitfalls of C/C++ from their experience at Google.
It's not a language that fixes C++ like D or Rust, but tries to get to the root of the problem, and the problem they identified was complexity.
Is your front-end/admin panel/... written in Go too? Because when noobs hear "We use Go",they'll think you're using that to generate webpages,CRUD apps,or write CMSes.
Python is still going strong. I use Python as well and still haven't found anything as good for getting started and running quickly without having some crazy typing rules or other "warts". There is not "Python: The Good Parts" book for a reason. Also for what I do Python has been plenty fast.
I wrote C modules here and there. Used cffi, that works great so far.
The thing is that those that don't switch languages usually don't write blog posts and those don't end up on HN (sorry for repeating it, I've already mentioned this in a sibling post). So the impression is that that's it Python and Node.js is dead, we should switch to something else.
Presumably in 2 years we'll see "We are switching from Go to <Rust|SomeLispThing|Swift|OtherNewThing>" posts. It won't mean Go won't still work well.
As for 2 vs 3. Yeah I am in the naysayers for 3. Sorry, for fueling the flames. But from my perspective it came too late and it didn't have enough benefits (or rather 2 didn't have big enough warts) so it ended up being very painful. I still plan on staying with 2 for now. We'll see if 3.5 or 3.6 bring about better tempting features and more 3 library ports get stabilized.
Because thanks to our experience with strong typed languages with native compilers and type inference, we know better.
Many of us have had the fortune to work with C, C++, Ada, .NET, Java, Delphi, Modula and Oberon derived languages, ML language family.
So we already know what modern strong typed languages, with native compiler toolchains, are capable of in terms of language features. And going Go feels a bit backwards.
Regarding Python, I never saw it more than a scripting language for system administration. ML based languages provided a better experience in terms of both performance and productivity.
My professional history is with C, C++, C#, Fortran, even years of Object Pascal in Delphi back in the day.
In no universe does Go feel like it's a "bit backwards", and I think you're trying to speak for a group without their input.
Indeed, an implementation I regularly use now is high performance algorithms in C++ (the Intel vectorizing compiler is superb) to function libraries, Go/cgo as the extremely efficient, very easy to write and maintain orchestration/manager.
I speak for the ones that got interested into Go as a mix of C and Oberon, even tried to initially contribute and went away as the language became a kind of Java 1.0.
The ones addressed by Rob Pike on his post about C++ developers.
The original article states: "One of Python’s most visible users, Dropbox — who also employs Python’s creator Guido van Rossum — recently announced it has migrated major parts of its back-end infrastructure from Python to Go" and refers to [1].
FYI some question TJ Holowaychuk's 'person.' A glance at his github commits would lead you to believe he is some open source prodigy, but there is a curious case being built (share=1 trick, no Quora login needed):
http://www.quora.com/TJ-Holowaychuk-1/How-is-TJ-Holowaychuk-...
I don't understand why people like go. It seems to be missing a lot of features and be pretty ugly and painful. I guess compared to javascript I can see the advantages though
Go could be improved in many ways. It lacks facilities that what we consider modern programming languages have, e.g. object-oriented programming, generics. The existing Goland solution to the generics problem is to have an almost duck typing approach of doing everything via interface{}. These are the cons.
The pros are of such value that they more than compensate for the cons: first class facilities for building concurrent programs and distributed systems. These are language features such as go-routines and channels and standard library includes for networking and RPC.
These are so great at what they do that they make programmers like me, who like Go, overlook the suck that comes from the existing typing system.
My personal dream endgame would be a dynamic language, such as Python or Ruby, that includes the concurrency features such as goroutines and channels. Directly as language features. AFAIK, the existing GIL in the reference Python and Ruby interpreters makes adding true goroutines impossible.
> The existing Goland solution to the generics problem is to have an almost duck typing approach of doing everything via interface{}.
I see this repeated again and again. It's wrong.
The "solution" to the generics problem is to not try to do anything that is generic, but do it specific: re-write that sort every time you need it for a new type.
People who have some experience in Go seem to tell that when you go this path you actually realize that you won't write them hundreds of time as was feared; it's completely manageable. Plus, you have your "sort" re-implementation right next to the struct definition, so you know it is sortable.
I knew about this solution. It's just that my inner Ruby dev screams "DRY!". Obviously it's so repetitive that it would be a bad sign in other languages.
I like more the solution used by the sort package. You can write generic code that delegates specific type code to a few well-defined functions, like ones that sort.Interface defines.
My personal dream endgame would be a dynamic language, such as Python or Ruby, that includes the concurrency features such as goroutines and channels
Erlang is dynamic and has all those features :-)
It's true that the GIL in Python prevents interpreter threads to run simultaneously. But for many use cases it's OK to use gevent or multiprocessing (which share the same interface!). Channels are there in the form of queues, but there's no built-in support for selecting from multiple queues. To emulate that, you need an extra greenlet for each queue.
> My personal dream endgame would be a dynamic language, such as Python or Ruby, that includes the concurrency features such as goroutines and channels. Directly as language features. AFAIK, the existing GIL in the reference Python and Ruby interpreters makes adding true goroutines impossible.
Have you had a look at Erlang and Elixir? The former is not as dynamic as Ruby (not much is), but it's a nice environment, and another step up from Go in terms of all the facilities for fault tolerant and distributed programming.
I second this recommendation: I've started a project with Elixir two weeks ago, and so far I really love it. As far as syntax goes nothing beats the elegance of Python, but in terms of overall application architecture OTP [1] is just miles ahead.
That said I can definitely imagine picking up Elixir for a purely imperative/OOP programmer being quite an undertaking. But definitely worth it.
I would like to mention LFE. Lisp Flavored Erlang (http://lfe.io/) is a great addition to the Erlang/Elixir world/ecosystem. Go on, test it out!
I work as an Erlang dev. It is really awesome. It has a simple and consistent syntax (even if don't like the comma, semicolon and period terminators), the most powerful native concurrency semantics I know, the best error detection and handling semantics, pattern matching (you make the compiler work for you), an awesome virtual machine that took correct design choices (gc per process, iolists for concatenating strings), incredible tracing support, good support for connecting with other programming languages, a good optional type system (Dialyzer, http://learnyousomeerlang.com/dialyzer) for detecting type errors and good patterns as supervisor, gen_server and gen_event . It also has a vibrant community that has created good libraries like Proper (QuickCheck-inspired property-based testing tool for Erlang) and Cowboy (simple http server).
I have worked with C, C++, Java, Ruby, Python and Javascript/NodeJs. I really like Python and Ruby as general programming language and for creating prototypes, but I would definitely use Erlang for any real backend project.
> My personal dream endgame would be a dynamic language, such as Python or Ruby, that includes the concurrency features such as goroutines and channels. Directly as language features.
Clojure is dynamic and has goroutine and channel constructs through core.async.
> I don't understand why people like go. It seems to be missing a lot of features and be pretty ugly and painful.
In other words, you have been reading about it, but never tried to learn it.
Go is incredibly easy to learn and prevents bugs and cruft as much as possible, makes writing documentation and testing painless and has good performance and concurrency support.
It also has a friendly, practically-minded community.
People like Go because of all the things Go does well. Here is a few examples:
* benefits of static typing at low cost to the programmer thanks to type inference and duck-typing,
* intuitive and easy-to-use concurrency model based on channels and go routines,
* functions as first-class objects,
* very good performance,
* clean, concise and simple syntax,
* novel, low-overhead approach to build configuration based on the convention-over-configuration principle (your import statements express all there is to know about how to build your software),
It basically takes all of the best parts from C++, Java, and Python, and fixes their bad parts. This has proved to be exactly what back-end and distributed systems developers have been screaming for.
I tried to like Go. I was allured by the native compilation and quite low memory footprint while still being quite high level, but I just can't. I can't stand it forces you to use K&R style. I can't stand the verbose error handling. I can't stand the inconsistency in the built-in types and libraries. I hate that unused variables and imports are a compile error which is just stupid and kills all the fun in programming. To me Go feels like a reincarnation of Fortran 77 with all the restrictions it imposes. There are some good and cool things about Go, no doubt about it but it many places it's just too cumbersome which is unforgivable in this day and age.
I'd argue placing error handling in a spotlight is a feature, not a bug.
Years of hiding error handling resulted in cultural biases that sanction focus on features without sufficient consideration for failure modes and unexpected conditions. Merely throwing an exception when something goes wrong may give you a peace of mind, but often leads to software which isn't robust against simple failures.
Similarly I would argue that lack of many OOP constructs is a feature as you can't over complicate stuff with class hierarchy and what not.
As to unused variables being compile error I guess it's good for big project but it would drive me crazy if GCC throws that in C code instead of a warning for my home projects as there is often a lot of tweaking and being forced to remove the imports between quick test runs would be very time-consuming.
Have you looked or tried Erlang? I like its error handling the best (isolate the fault). At least it handled and manages issues with large concurrent backends well.
Strict typing after JS is like a breath of fresh air. Multiple returns are helpful. Parallelism is real, first class, brilliant. The whole thing is intuitive. Most importantly: at every interesting design decision it's easy to pinpoint which language they got burned by the opposite. It's written by truly experienced people standing on very practical grounds.
Not a lot of them - just some. And the missing ones, a lot of people don't miss anyway.
It also has things others languages don't - fast compilation, a big company behind it (while staying opensource), and simplicity.
> be pretty ugly and painful
Subjective. I like how it looks and have no pain.
> compared to javascript I can see the advantages though
It is not just "better than javascript". It is as expressive as ruby or python, with as much type safety as possible without giving up clarity or speed. And its type system doesn't require weeks to wrap your head around it.
> has things others languages don't - fast compilation
Never understood this talking point. What language other than C++ (and C to some extent) doesn't have fast compilation? And compared to these languages Go gets most of its compile speed simply by doing a really poor job optimizing. Compare times for -O0 and -O3 on other languages to see most compile time is dominated by optimizations.
Is this supposed to convince C/C++ programmers? Like "sure your program will run 50% slower and have garbage collection pauses, but it compiles faster!". This just boggles my mind.
I think this depends strongly on your development style.
If you come from the world of scripting languages, a common style is "write between one and twenty lines of code; run tests; edit three lines; run tests...", where "run tests" might literally be that, or might just be running the code to sanity check that things are not too broken. In this style, even a twenty second delay would become very painful.
I think people who learned on C, C++ or Java tend to write much larger pieces of code in between run attempts, simply because it takes (or took) a while to check your work, instead of being effectively instantaneous. I know at a previous position where I did some Java development, the "tomcat stop; ant remove; ant clean; ant install; tomcat start... okay, NOW you can test" was quite difficult to develop against iteratively, sometimes being measured in minutes instead of seconds.
> the "tomcat stop; ant remove; ant clean; ant install; tomcat start... okay, NOW you can test" was quite difficult to develop against iteratively
Ok this makes even less sense to me. In 10 years when Go has the completeness of these big Java systems it'll be even worse since there won't even be a dynamic loading option and the only choice will be to restart the entire system like that.
If you want to like Go because it has fast basic features and that's all you need that's one thing, but it doesn't have anything to do with compiling speed does it?
I like Go too, but lets not kid ourselves here. Ruby is vastly more expressive than Go. (I'm sure Python is too, but I am not a Python programmer, so I am not in a position to say).
Incidentally, your link includes a great example of Go's error handling - which is inevitably what actually happens in languages without exceptions: errors are silenced and the program marches on, each step making less sense than the previous. It's a good talking point that you can always check error values - but it never really happens, in part because library designers try to avoid putting the burden on themselves and their users:
"Getenv returns the empty string and continues. Then Go somehow manages to parse the empty string as an empty JSON list and still continues. Then it tries to interpret the first of the user arguments to the program as the path of the program to run and execs that instead! Utter failure."
It seems that having exceptions in the language is a great predictor for libraries/built-ins barfing upon bad input vs silently producing garbage (as in JS's "undefined" string produced from undefined values and propagated, or Go's behavior above, etc.) For instance Lisp's NTH produces garbage and it predates Lisp's exception handling features whereas AREF was added later and indeed complains loudly, etc.
>It seems that having exceptions in the language is a great predictor for libraries/built-ins barfing upon bad input vs silently producing garbage
Maybe so, but having exceptions in a language is also a good predictor for the misuse of exceptions for purposes other than error handling. For instance, Python has the StopIteration exception to signal the end of an iteration.
Exceptions force API designers to decide whether or not a situation is exceptional enough to force a stack unwind on the caller's end. That's not something that's necessarily decidable from the point of view of the library.
For instance, say you have a function http.get(url). Should a 404 response automatically raise an exception? What about a 301? A network issue? Surely, for a crawler, a 404 is not exceptional enough to merit a hidden goto that unwinds the stack frame (by default). The designer of the http library cannot decide which status code is exceptional in every application.
It's similar with the results of SQL statements, file system access and all sorts of other IO related stuff.
It seems to me that the more complex a system is, the more it needs a very specific error handling strategy anyway and doesn't benefit from library designers' opinions about what is and isn't worth a stack unwind.
First of all, sudden stack unwind comes with a greater mental burden than regular structured code. Something implicit is happening that violates the expectations we have based on what we can see.
Secondly, consistency is always important because inconsistency forces us to think about things that we shouldn't have to think about, which lowers our productivity.
I could get behind the Go compiler to forcing people to write "_ = errReturningFunc()" instead of simply "errReturningFunc()" if they want to explicitly ignore errors.
In my recent experience, it actually bothers me a lot that funcs in the standard library would often rather return nil or the zero-value of a type than change the signature of the func to return (T, err). I don't really care that the docs describe that behavior -- that behavior is an error.
The thing is, compilers can force people to refer to error variables, but they can't prevent people from returning array[0] when i is out of array[]'s bounds, an empty list given an empty JSON string, etc. And forcing the former unfortunately only encourages the latter.
* Getenv doesn't return an empty string for a non-existent env var?
* Go JSON parser doesn't return an empty list given an empty string?
That you can handle errors without exceptions needn't have an existence proof... The question is how many errors are silenced. Stats will be hard to come by. But getenv and JSON parsing are pretty basic functionality and in most languages with exceptions they would not silence errors. (say, Python's json.loads barfs and os.getenv returns None which unlike the empty string will almost certainly lead to an exception if the code won't account for None). So it's a good anecdote in the absence of hard data.
Sorry, I missed the blog post. The Go code in the post is garbage. It doesn't check errors, which all good Go code does. (His plan to "add error handling only if the compiler told [him] to" is a bad idea.) I talk about the Go philosophy of error handling here: https://www.youtube.com/watch?v=dKGmK_Z1Zl0#t=27m10s
json.Unmarshal only returns an error value, so it never "returns an empty list". Instead you provide it with a []byte of the JSON data you want decoded and a pointer to the data structure into which to put the decoded data. If you don't check the error value returned by json.Unmarshal then you don't know if it decoded anything or not. That's why the author is left with an empty list.
In reality you'd add two lines to get the following code, which does not proceed past the failure in json.Unmarshal: http://play.golang.org/p/rYfwncjU2f
An aside: os.Getenv doesn't return an error value because it's a convenience that is mostly used in contexts where you don't care if the variable is set or not (in the shell you usually don't care either, you just test for != ""). If you actually care you can inspect the environment with os.Environ. But in this case it doesn't matter.
And here I thought you were talking about the first example in the blog:
fmt.Println("Hello, world")
Now what happens when program opens a file and is run without stdout:
./program >&-
The file it opens is fd 1 and the program prints to the file instead of printing to the console. An odd case that has caused security holes in the past. In languages that fail on errors if they print anything before opening the file then they don't corrupt the file.
The default and laziest case for errors should never be to just hide them and continue on.
That post is a piece of garbage. He's clearly angling for a language like Rust or Haskell that has a very complex type system for preventing errors in the code, and no other language would succeed with the way he was writing code (which was completely inane). It's like he jumped in a plane, hit full throttle ahead and complained the plane crashed into the ocean instead of landing him safely in Seattle.
Getenv returns an empty string just like unset env variables act like an empty string on the command line. If it returned an error, people would complain it works differently than they're used to. You can't please everyone.
With the exception of speed, why does Python need a replacement?
I am using Python daily, and pretty much all performance problems (with my work) can be solved at the database or caching level. I get the impression that Numpy can produce reasonable performance for numeric problems.
In my experience developer productivity is of far more importance to business than language performance (obviously that depends on your ___domain). I do get asked to speed things up. But I get asked for "something working" by yesterday far more often.
The blog post gives the rationale; it's a combination of performance, a hope that static typing would make it possible to avoid a class of errors 0install had been experiencing, and wanting to ship native binaries with no dependencies - a pretty specialized use case, but one that 0install happens to need. (I'm aware that things like freeze exist, but they're not really first-class citizens, and the startup time - very important for a command-line utility - is not great).
In general I agree with you, I was a big fan of Python until I discovered Scala. But it's not a great fit for the 0install use case, and as you'll see from subsequent posts, switching to OCaml turned out to increase reliability and performance without sacrificing concision or development productivity.
> With the exception of speed, why does Python need a replacement?
Depends what you use it for. It's very good for a subcategory of problems, in particular prototypes or glue code. However, it leads to "use your test suite as a compiler" for large scale projects due its lack of static typing.
I do like Nimrod. It has been around for a while. Has good syntax, good semantics (things it operates with). Very fast.
Sadly it doesn't have the advocacy and hoard of developers supporting it and writing libraries for it. Certainly no big company with billions of dollars of revenue. It is unfortunate.
I feel like Google should have just taken it and used it as Go back then. I would have been a good choice.
There is also GNOME's Vala language. More focused on GLib but the idea is the same. C# like language compiles to C. Good performance. But again kind of fringe.
This "fringe-ness" in longer term translates in less libraries/frameworks. With Python if I am starting on something new, I know I can probably find someone that wrote a library related to it. Scientific computing, AI learning, graphics, GUI bindings, http parsing, WSGI middleware, strange protocol parsers, libraries on top of C libs (parse .pcap files) and so on. All are just one search and download away.
With Nimrod (or any new language) I am afraid I would be writing those by hand.
> There is also GNOME's Vala language. More focused on GLib but the idea is the same. C# like language compiles to C. Good performance. But again kind of fringe.
It seems like native imperative languages with automatic memory management has just fallen by the wayside as history has progressed, or have been relegated to niches. I wonder why that is.
Java happened. Sun took the JIT from SELF and everyone went JIT, repeating the VM everywhere from the P-Code days. Forgetting the native wave that followed.
However Java and C# do have quite a few native compilers available. They just tend to be forgotten on discussions about them.
> However Java and C# do have quite a few native compilers available. They just tend to be forgotten on discussions about them.
Are there any viable ones for java? It would be pretty cool if one could leverage some of the java ecosystem without having to include a vm. EDIT: I'm guessing that making command line utilities would be more viable, for example.
Atego, Jamaica and J9 are not full native compilers, rather JVMs with support for AOT deployment, similar to .NET NGEN/JIT story.
Additionally Oracle has kept the Sun's work from the meta-circular JVM, Maxime as Graal and Truffle. Which may replace Hotspot for Java 9 or later and being used by AMD/Oracle for the GPGPU support.
This Java meta-circular compiler has support for JIT and AOT compilation.
I was kind of expecting this. Although I like Go (and prefer it to NodeJS), I hope forthcoming feedback on TJ's "life choices" does not degrade into a "Let's move from Node to Go" echo chamber.
More importantly, I hope the Node community's self-centred "holier than thou" doesn't bleed over, given that Go has (at least so far) kept a fairly high standard of discourse.
That said, I, for one, welcome more contributors to the Go ecosystem. It is a good systems programming language, but it needs a few more "horizontal" libraries to make humdrum tasks (like parsing, accessing databases, etc.) more palatable.
Thanks, sublime tex and vim with plugins are still a long way off what you get from a good ide. Just glancing there is no real refactoring support, its more around auto complete.
I am aware it is powerful and has as many features as an IDE but seems like it will take a fair bit of time to learn (on top of learning a new language). Eclipse is fairly intuitive by comparison.
I use LiteIDE to good effect. It has a few kinks to work out but is generally everything I need. The Go intellij plugin is supposed to be good too from what I hear.
Packages are shared across projects in the same gopath, you could run separate gopaths for isolation.
I've found the Go plugin for IntelliJ to be flaky around the things I most want. Particularly refactoring. It would also be nice if it borrowed the behaviour of the sublime and vim plugins and fmt'd code on save.
I'm using Go only for experimenting. IntelliJ worked great so far and I'm saying this as a person who works with Visual Studio + Resharper in his day-job.
So what comes after Go? I only ask because I figure if I start learning that now, by the time they switch again I will have a fair chance of being competent at it by then...
I wonder why they didn't choose Go in the first place. Both languages were introduced in 2009, I remember evaluating both, and choosing Go because it was clearly superiour when the goal was serverside, speed, stability, maintenance and simplicity.
You're missing that OCaml isn't stuck in 1999. OCaml now has an excellent package manager, cool new features, lots of system libraries, and a growing community. What do you find out-dated about it? Check out http://www.realworldocaml.org
I want to serve a JSON response over HTTP, preferably from a standalone server (like django etc). Later I want to talk to Postgres and memcached.
Do I use this thing? http://ocsigen.org/ocsigenserver/ All the docs either don't do what I'm looking for (i.e set up a web server to serve some static files) or are broken links!
OCaml is actually what I'd prefer to use (since I had a blast with SML/NJ)
I'll check out that book, thanks! But I did just skim the ToC and it has nothing about serving HTTP. Serving HTTP is like my #1 use case for anything these days :/
Scala 2.12 will have a new compiler backend which should speed things up considerably. [1]
Other than that, as an avid Scala fan, I've been long wondering why people favour Go so much. Arguably, if you've started out with RoR, then Node.js was a great improvement (dynamic typing with awesome speed). Then came Go, which solves many of the issues you tend to encounter with Node.js. So now, after it has reasonably matured, many people are pivoting to it.
Scala, while having a rather "bloated" core library (i.e. quite exhaustive), already does most that Go does (i.e. an Actor is reasonably close to a goroutine etc.) and has an awesome type system. But then, I'm biased and YMMV ;)
Compared to Scala, Go is incredibly simple, both to learn and to use. If you don't have a lot of experience with Java and the JVM, Go also avoids that whole avalanche of complexity, apart from Scala itself.
I meant only that if you want to use Scala, you'll inevitably have to also know Java. It's two languages for the benefit of one. The JVM comes with its own issues: which JDK do I use[1]? What happens when one library I want to use recommends a different JDK than another library I want to use? Build tools questions: ant, maven, gradle? Oh, I need to learn Groovy, too? Three languages for the benefit of one. Yay.
There's just an enormous amount of stuff to learn, and most of it is required-but-incidental; none of it (except Scala, in our example) is an inherently necessary part of getting from learning to a production system running Scala on the JVM, but you will end up having to become conversant with many of these things, and probably dozens of similar infrastructure and tooling systems.
Now I don't know if it's intentional or not, but many things you are saying are just FUD. You seem to be assuming that the only way to do JVM stuff is considering all the difficulties that enterprise Java shops with legacy projects put up with. That is far from the truth, as any tutorial for Spray, Play or Akka could tell you.
> Which JDK do I use[1]?
The Oracle JDK (which is the same as OpenJDK FYI).
> What happens when one library I want to use recommends a different JDK than another library I want to use?
There is a 3-month period or so every three years when a new major Java release is done when some developers of enterprisy libraries might want to do some more testing before making a recommendation. It's not a big question in the JVM world at all, and it's definitely not a big problem even for early adopters.
> Build tools questions: ant, maven, gradle?
SBT. You're building a new Scala project.
> most of it is required-but-incidental; none of it (except Scala, in our example) is an inherently necessary part of getting from learning to a production system
You would have been right five years ago. Today, many people run Akka/Spray/Play projects in production just fine without deeper devops knowledge necessary than with other runtimes.
> You seem to be assuming that the only way to do JVM stuff is considering all the difficulties that enterprise Java shops with legacy projects put up with.
Ah, that's because that was the only place I've had much experience with Java and Scala. We wanted to use Elasticsearch (Java) from our CMS (Java), and the recommended way to do that (at the time: embedding ES in your application as a search-only node) turned out to be infeasible, due to ES and the CMS (which was started in 2006ish) being unwilling to share any specific JDK without a lot of code changes to the CMS. We ended up building a system involving RabbitMQ and a thousand lines of PHP, as the easiest solution. :(
So, yeah, I recognize that a lot of my bad feelings about JVM languages are not particularly relevant to green-field development, whether in Java or Scala. I just got ranty. Sorry.
Why wouldn't you just run ES as a standalone server and use its REST API? ES is a core part of the stack at the startup I work at and it never would've occurred to us to run it as an embedded service.
You'd run the data nodes as standalone servers, but the recommended way to talk to ES from your Java app was, at the time, to embed ES as a non-data node in your app, which means that you could talk to ES in-process, and the local ES would be part of the cluster, just pass on queries and data to the data nodes. This was 2011 (0.18.x or 0.19.x, I think), so maybe that's not the recommended way any longer. The REST interface was also available, and recommended for anything that wasn't Java, and that's what we ended up using (but given the opportunity not to write the code that interfaced between database and ES in Java, we took it, and wrote that in PHP, with just a tiny bit in Java to push a job on the queue).
It looks like that's still what's happening in the Java API: http://www.elasticsearch.org/guide/en/elasticsearch/client/j... I'd like to reiterate that moving our app to a more recent JDK would have also been a good solution, except that we didn't have the dev and qa resources at the time to devote to that.
Citation needed. Hackage goes to great lengths to validate packages as much as possible. Other support systems do continuous integration and further validation, if you're looking for well regarded package subsets.
Maintaining 6000+ open source packages is a pretty serious task.
I dunno, I tried installing snap, yesod and happstack (the three top web frameworks apparently) about a month ago and after about 20 minutes of compiling all failed to install (some had missing packages, others had the packages but they failed to build). I'm running a no-frills MBP with bash, which I would imagine is a fairly popular dev environment.
I think you should figure out what's going on with with your dev environment and go with Haskell. Are you using the Haskell platform? If so I would ditch that and make sure to install everything in a sandbox, I've had very little trouble with cabal since I went with just cabal + sandboxes. I'm on linux but Chris Allen's guide has instructions for a minimal OSX install: https://github.com/bitemyapp/learnhaskell
If none of that helps, come to freenode #haskell, those packages really should work.
OK, you gave me the encouragement to try it again.
I ran into a bunch of bugs getting haskell platform set up correctly on OSX (wouldn't remove my old version, had to manually remove GHC, also reported this one https://github.com/haskell/cabal/issues/1980) but after reinstalling Haskell platform it seems to be working better. Thanks.
There is also a known issue with XCode and OS X >10.9, which may cause some packages to fail to compile. Haskell Platform download page includes instructions on how to avoid it: http://www.haskell.org/platform/mac.html
If you are using the GHC and Haskell-Plataform provided by your distro, I'd recommend you get the latest version and install it yourself. Both are changing a lot and some distros (Debian, for example) do not keep up. (Also, that'll avoid a few severe bugs GHC had up to a few years ago.)
No generics (parametric polymorphism), no algebraic data types. You should learn some Haskell or Ocaml even if you don't plan on using it in production. Go's type system is weak.
Edit: I don't think there's anything like type classes either but I'm not 100%.
I don't understand why all the ML-lovers have to bash Go for not being OCaml or Haskell or Rust. It's like bashing Python for not having static typing. Go is not one of those ML languages with a complicated type system. It has a simple type system. This is a feature for Go, just as dynamic typing is a feature for python. Neither is right or wrong or backwards. They're different design choices. If you don't like it, that's fine, don't use it. But it's not an inherently bad choice.
Yeah, I mainly want to get a feel for building a real system using a strict type system and algebraic data types. I've done some toys with them but nothing real yet.
I see the lack of algebraic data types and type classes as a feature, honestly. It means I can learn the things I need and start working in 2 days instead of in 2 weeks or a month.
I sometimes need generics, but not frequently enough to miss them.
You think Go's type system is weak. I think Haskell's type system is overcomplicated. So, there.
Even if it were true that it were overly complicated, that wouldn't change the fact that it's much more powerful than Go's.
“When I work at this system up to 12hrs a day, I’m profoundly uninterested in what user interface a novice user would prefer.” —Erik Naggum
Are you using visual basic because you could pick it up in 2 days instead of taking a month to learn Go?
It's easy to learn because it doesn't do anything interesting that you're not already familiar with. If you're not missing them, you're missing out on simple beautiful abstractions like map and filter. You're also missing out on type safe libraries for containers. It's not possible to write a generic container without casts to interface{}, which is a shame imo.
Bringing The Language Which Shall not Be Named to the discussion is a low blow. But I deserve it. My phrase about overcomplication was flamebaity and uncalled for, and I apologize.
> you're missing out on simple beautiful abstractions like map and filter
The thing is, in Go, those take almost as much space as a plain for loop.
I know, you will tell me "that's because Go's too verbose". I will grant that it's more verbose than Haskell.
But I am not doing maps and filters all the time in my code.
> It's not possible to write a generic container without casts to interface{}, which is a shame imo.
My point is that generic containers are the feature where generics are genuinely needed. And in those cases interface{} makes it possible. Not super-awesome, but possible. I actually like that the language doesn't bend over to fulfill something that looks almost like an edge case. It is not "programming with mathematics". It's still "moving bits around". But the bits can be moved with ease.
interface{} doesn't give you generics. The point of generics is to give you two distinct things:
1. You can write code that performs identical logic for a range of different data types, without having to know what they are.
2. That code can be checked for type safety.
interface{} gives you half of 1. You can write code that performs common logic and takes an interface{}, but then that code has to manually switch on type, or convert type before running.
Which gives you trouble with 2. Once you don't have a distinct type, you can't check for safety. All the compiler can do is check that an interface{} is passed in; which is a pretty weak guarantee. Meanwhile, in languages with generics, the you can write a generic method that uses the + operator and the compiler can check whether it works for numbers (OK), strings (OK), HTTP servers (uh oh, stop the bus!)...
Go's type system being weak is a factual statement. Haskell's type system being overcomplicated is an opinion.
One might prefer a weak type system over a strong type system, but that's a different discussion. The parent clearly expressed that he wants a static strong type system.
I'm not saying Go is a weakly typed language. I'm just saying that the statement "Go is a weakly typed language" is a factual statement that may be true or false. You were wrong in positing the claims "weakly typed" and "overcomplicated" as if they are somehow equally valid, because one is a factual claim and the other is an opinion.
In the most conventional definitions, Go is a strongly typed language. So this factual statement appears to be false.
As always, there is some confusion in this topic about dynamic typing vs static typing. There seems to be plenty of dynamic typing in Go, which in itself does not make its type system weak.
Go's type system being weak is a factual statement. Haskell's type system being overcomplicated is an opinion.
Calling one weak and the other overcomplicated are both completely subjective, biased statements.
And no, some random blog doesn't count as a citation: There are zero legitimate, agreed to sources that will back up your definition. Instead it's people painting broad strokes to bias the world towards their own beliefs.
Just as unreasonably I could say that Go has a Clarified Type System, versus the Conundrum Type System found in Haskell.
Are you aware that the notions 'weak' and 'strong' are actual terms used to describe type systems [1] ? Did you bother to look that up before going overboard and immediately accuse me of bias? I don't program in either Go or Haskell.
Now whether Go's type system actually has the property of 'weak'ness is very debatable. But whether it is true or false, it remains a factual statement.
You should read the first sentence in the page you linked. To make matters even worse, none of the "weak" notions even apply to Go, and I thought you were talking about something entirely different altogether given that Go is by zero definitions, colloquial or not, "weakly typed".
The post that set this off called Go's type system "weak". They were not saying that it was weakly typed.
It's a choice really: using a built-in exhaustive type system, or creating one manually with unit-tests. Unless you are happy with certain types of bugs.
I agree. JavaScript is weird. I think ECMAScript will make a lot things better, but it will still be a couple of months and it still won't fix it all - still a huge step of making it a really usable language for many things.
Node.js is becoming mature, less trendy. I really find it weird how people compare it age wise with Go. JavaScript is way old than Go or other languages. V8 is also older than Node of course. ECMAScript didn't have breaking changes in a really long time. There are many, many implementations. SpiderMonkey has been used on the server side for over a decade now.
Go looks great. There are some rough edges though and whether really good solutions will build up for these things is a really interesting thing to look at.
It is really nice to see Node.js, Go and Rust emerging in amazing ways, all of them fixing problems in amazing ways. I love how great concepts, like node.js streams and pipes are copied to Go and Rust in ways that match their styles, not just blindly.
All these things even influence languages like Java and C++. Who would have known only a couple of years ago that things would emerge in such ways and that it needs some projects with the idea of yet another programming language. What is even more interesting is that a lot of concepts actually stem from Perl... well, not necessarily the language itself, but libraries, modules or Perl6, which arguably was/is a really ambitious research project. It's a bit how many concepts took ages to be ported from Plan 9 to other operating systems.
Anyway. It is great to see how people nowadays look at other projects and don't judge by first impression anymore.
At least it seems like it. Node.js looked extremely awful to me in the beginning and turned out to actually not be (despite its shortcomings and JavaScript, which also turned out to be nicer). On the other hand projects, like Meteor that looked at least okay in the beginning turned out to be way more awful than they looked when I first heard that they don't even support proper REST.
I know, my opinion on this might not be really popular, but it's amazing to see how so many new concepts emerge, even when they seem crazy, sometimes turn out to be crazy, sometimes turn out to be amazing. It's hard to know where we will stand in a couple of years. However, I don't think only one of Rust, Go or Node.js will make the race and I think none of them will look like they do today in one or two years, especially when it comes to their ecosystems. Just because all of them are too young to be judged upon and all of them are changing too rapidly (or new standards are upcoming, as with ECMAScript), so that nobody really has or can develop a deep understanding of the language/framework yet, not even its developers.
What I really hope though is that there will soon be more big projects than just Docker and a bigger ecosystem.
Conversely, Python is a great language but it's not as easy to make it go fast. It's slow, but it's great to use. We also knew that when we signed up.
It's great that Go is getting more mainstream adoption! Deservedly so. But it's probably still easier to be super-productive developing a CRUD app in Ruby or Python. And it's still easier to share code between backends and web frontends with Node. If you don't need either of that, and you do need performance, then, yes, maybe you shouldn't pick Python or Node.
I agree that Go is a great option to consider, but Zef is framing it a little as a silver bullet, and well, of course it isn't.