Node.js vs Golang: Battle of the Next-Gen Languages

Node.js vs Golang: Battle of the Next-Gen Languages

Recently, there have been criticisms about the value of using Node.js in a high-performance, networked application environment, and some developers have moved to the Go language.

There are also several high-profile corporate examples switching to using Go, beyond the creator of the language, Google. Dropbox has moved to Go, claiming significant performance increases, and the developers of the Docker virtualization system are also using Go.

It’s important to note, however, that Node.js is still used by a much wider audience, has more modules, is easier to use, and isn’t going anywhere anytime soon. Also, if you’re making a web application, Node.js will probably be your language of choice, as Go is currently used more as a scripting language when focus on concurrency and speed is the priority.

In this article, we will take a look at the differences between Node.js and Go from the developer’s point of view to uncover the strengths and weaknesses of each environment.

Node.js and the Javascript Language

Node.js Emblem

Node.js emblem

Node.js (and its recent fork, IO.js) is an increasingly-popular platform built on a fast, JavaScript-based runtime: V8.

V8 is a JS virtual machine created by Google that is designed to build scalable, networked applications. It compiles JavaScript code to native machine code, using some complex optimizations. V8 also does the memory allocation and garbage collection of JS objects.

Though these dynamic optimizations for a dynamically-typed language offer a lot of flexibility for developers, they do come with some performance costs at times.

As Node.js is written in JavaScript, it inherits most of the properties of that language. JavaScript is so popular these days that the ECMAScript standard development is done mainly in an evolutionary fashion, rather than a revolutionary fashion.

This has some important side effects for JavaScript and Node development:

  • Some of the JavaScript language flaws are difficult to fix without breaking backward-compatibility, though the worst issues are being fixed.
  • Useful, but radical, JS language features may not be implemented or only be “patched on” as an add-on syntax. This can lead to a messier language design compared to languages that integrate features cleanly into their design. A good example of this is concurrent computing with JS. JS best practices for concurrent computing went from a concurrency API (using event-based callbacks), to the devolopment of promises, to the coming support for async generators. These days callback hell is still a serious issue with many Node.js applications; however, this has led to less readable code, slower development, and perhaps even more bugs.

All this means that the JavaScript language evolves rather slowly (and some would say poorly too), even when good concepts from other languages are known to work better.

Node.js still has a huge community and tons of great applications being written for it, so we don’t want to scare you away with some of its pitfalls in small cases; it’s still a great platform to work with, according to the vast majority of developers.

The Go Language or Golang

The golang gopher

The Golang Gopher

Go, which is also referred to as “Golang,” is a compiled systems-oriented programming language started by Google in 2007. Go can be considered the result of a rather conservative language evolution from languages such as C and C++.

Go improves upon some of the misgivings of those languages:

  • poor dependency management
  • cumbersome type systems
  • difficult memory management
  • lack of parallel computation support
  • lack of multi-core support

Go also reduces the amount of code typing needed by being more expressive than C or C++.

Go makes it much easier to write robust, networked applications, without sacrificing much in the way of performance, compared to C or C++. The high performance is in large part due to the static compilation of the statically-typed Go code. A lot of optimizations are possible when a compiler can do all the code inspection work beforehand, as opposed to the dynamic JS compiler work done during runtime.

Golang vs Node.js Comparison of Features

We can begin to see why, for some types of application development, it might be useful to use Go instead of Node.js; however, Node.js is still a very useful language in many use cases.

Let’s compare the strengths and weaknesses of each programming language, so it may be easier to choose which environment is the right tool for your next job.

GoNode.js
MaturityMature and robust for its ageMature, but the API is still somewhat changing. The recent IO.js Node fork changes might also become a cause for API problems for developers writing and using Node modules. How big this problem will be is not clear right now.
PerformanceSimilar performance characteristics as with C or C++, which is to say very goodDue to JS’s dynamically-typed nature, Node can not reach the raw performance of CPU or memory bound tasks that Go can achieve in many tests. However, in the common use cases where network communication or database interaction are involved, the performance of Node and Go are often equal.
ConcurrencyGo uses coroutines called goroutines. A goroutine is a lightweight thread managed by the Go runtime. Communication between goroutines is done very elegantly using channels. For more, see this video.Node suffers from JavaScript’s less than elegant concurrency support using the event-callback mechanism. However, for a lot of applications, working with JS promises and the coming async generator support (also called “semi-coroutines”) will suffice. Something like the Koa framework is already supporting the async generator approach in Node.
ScalabilityGo was really designed for scalability and concurrency, without too much hassle.Several people and companies using Node.js have made claims that Node has some problems in environments which need to scale massively. Perhaps Node can overcome these massive scaling issues in time.
Ease of DevelopmentPeople coming from a JS/Node background will need to learn some new programming concepts, such as: coroutines, channels, strict typing (with compilation), interfaces, structs, pointers, and some other differences.For a JS developer, it is really easy to get into Node programming.
Frontend & BackendThough you can run Go code in the browser using gopherjs, JS still is the way most developers like to program the frontend. Go is aimed more at the backend, in particular for developing high-performing concurrent services on the server-side.Not having to do a mental context switch while developing a JS-based client-server system is really nice.
Packages & ToolingThe number of standard Go packages is growing steadily, currently at over 100, and the Go community packages can be searched easily. Though there aren’t as many different developer-friendly application frameworks to choose from as compared to Node yet, you can take a look at the “go get”-able packages from the Go community, which currently sits at over 58,000 available for use and growing.The number of Node packages sits at more than 100,000 currently. This means that a lot of groundwork has been done, and that can make certain software projects a lot easier and/or cheaper to implement. Node’s tooling is also superb. The npm package manager learned from all the package managers that came before and did most things right.
Developer Mindshare A recent study showed the rise of Go to a place in the top 20. The pace at which this happened exceeded expectations. Go definitely has a lot of momentum building up, especially with the recent support of the Android mobile OS.Node is much more popular at this time by many orders of magnitude. Getting good hosting support, commercial support, and Node.js freelancers for your project will be much easier for NodeJS at this point in time.
Error HandlingError handling in Golang requires you to implement explicit error checking, which can make error troubleshooting difficult. However, some argue that you get a cleaner application overall, once you understand Golang error handling. Error handling in Node.js can be inconsistent at times, but it does offer the more common throw/catch mechanism for errors that developers are accustomed to using with other languages.

Summary of Node.js vs Golang

The choice between Node.js or Go very much depends on which type of development suites you best and how massive the network service needs to scale.

Go may not yet have all community packages or mindshare that Node has, but its syntactically cleaner concurrency model, better raw CPU- and memory-bound performance, and its ability to scale up better with concurrent loads could make for a better foundation for certain network application types.

If you need certain Node.js packages that are not yet available for Go and that would be difficult or expensive to re-implement in Go, then Node may be the wiser choice.

If you feel like installing Go on your Ubuntu/Linux system, have a look at our guide to installing Go. Then visit GoByExample and the online Go book for some more great tutorials.

If you wanted to give Node.js a shot, be sure to check out our guide to installing Node.js, as well as our list of free Node.js hosting services. Then head on over to NodeSchool.io for some great tutorials on programming with Node.js.

Questions or Comments? Ask Jacob!

Ask a question and Jacob will respond to you. We strive to provide the best advice on the net and we are here to help you in any way we can.

  • Dmitry Vyukov

    You point to godoc.org and at the same time say “dwarfs the packages available for Go (in the hundreds currently)”. Only http://godoc.org/-/index contains 58000+ packages. Please fix the article.

    • Hello Dmitry,

      Thank you very much for your great comment and the additional information. I’ve gone ahead and updated the article to reflect that while the standard packages available in Go is only in the hundreds, the ‘go get’able community packages is up over 58,000 and growing.

      We always strongly value developer and reader input, so thanks for taking the time to stop by and help us get the best advice out to the masses!

  • Hello Dmitry,

    Thank you very much for your comment and the additional information. I’ve gone ahead and updated the article to reflect that while the standard packages available in Go is only in the hundreds, the ‘go get’able community packages is up over 58,000 and growing.

    We always strongly value developer and reader input, so thanks for taking the time to stop by and help us get the best advice out to the masses!

  • Ken Fromm

    FWIW, we wrote a couple of posts on our experiences in moving from Ruby to Go for our API and backend service architecture. We did this several years ago and it was one of the best decisions we could have made.

    http://blog.iron.io/2013/03/how-we-went-from-30-servers-to-2-go.html
    http://blog.iron.io/2013/08/go-after-2-years-in-production.html

    • Wow thanks Ken!

      I read over your blog posts and that’s very cool to see Iron.io was the first company to post a Go job on the Golang message board, and that you ended up snagging one of the core Golang developers.

      Any updates since the end of 2013? Are you even more proficient with Go now as more developers are using it and more packages have become available?

      • Ken Fromm

        Our productivity and usage have improved over the years but a large part is just being able to hire great Go developers. Go does provide a definite advantage because good systems engineers like to work in Go.

        There were a few issues we ran into in the first year with low-lying bugs within packages but those were fixed pretty quickly once we were able to pin them down. The larger issue we’re running into now is around dependency management. There’s some tooling around it (godep) that works well but there are still hoops to jump through to allow for easily reproducible builds. We expect to see some improvements over the next several months though as it appears to be a hot point for the community.

        Moving up from just Golang, another issue has been in isolating issues across the stack. We’re using Docker pretty heavily. A primary use is for containing the various language environments that IronWorker support, which allows us the capability to support multiple language versions within a low-latency job processing environment. We’ve also been Dockerizing other areas of our deployment stack. Using containers makes deployments a lot easier but it also brings challenges when it comes to isolating problems or bugs.

        Go provides a great debugging framework but when issues arise we’re not always sure whether it’s with the OS, Docker, or the application itself. No show stoppers but just a lot of extra cycles of trying different versions of each component to nail down the source. Improved Docker debugging would go a long way here.

        FWIW, here are the posts on our use of Docker. We’re definitely on the farther range when it comes to heavy use of it. (Primarily because of the ephemeral nature of a worker system.)
        http://blog.iron.io/2014/04/how-docker-helped-us-achieve-near.html
        http://blog.iron.io/2014/10/docker-in-production-what-weve-learned.html

        Happy to get provide more information if you’d like.

        • Awesome, thanks for sharing your experience Ken!

          I think you brought up a really good point about being able to hire great developers, I’m sure no matter what language a company decides to go with, that’s a huge determining factor on how efficient they can be.

          It’s also cool to hear about your massive amount of Docker deployments, that’s something we’ve noticed as well talking to various companies relating to the web hosting field. There is a very large push to start leveraging new technologies like Docker to ease the process of supporting multiple environments and not worry so much about the underlying infrastructure constraints.

          Thanks again for the update, I’m sure others that are thinking about making the switch to Go could find your use case of it helpful to determine if it’s right for their needs.

  • Sven Slootweg

    You’re missing the data point of error handling – while the error handling in Node.js can be inconsistent, the error handling in Golang is just consistently wrong. It requires you to do explicit error checking (C-style, which is known to lead to many, many problems) and apparently does not offer any kind of throw/catch-like mechanism.

    This alone is enough reason for me to never ever use Golang, and stick with Node.js – making the right thing hard to do (like Golang does) is practically guaranteed to lead to unreliable software.

    • frankel0

      I think that is a good point. Though I also believe that there are some advantages to Golang that are hard to ignore. Go routines are extremely useful and are simple to implement. In Node.js I find that even for simple scripts you end up with callback-soup, using an async library, and using Cluster just for simple parallel processing.

      We will update the article to cover error handling though because you point is an important one.

    • Daniel Souza

      You can kinda throw/catch using Panic and catching the panics, but I personally believe explicit error handling is better, so to each his own. I’d rather treat errors locally when they happen than bubble them up… it does get verbose though, but I generally believe that explicit is better than implicit.

      • Sven Slootweg

        That’s 1) completely missing the point and 2) dangerous.

        You shouldn’t “treat errors locally when they happen”, you should handle errors where it is *appropriate* to handle them (which is often not the same level at which they are thrown). If errors do not bubble up, you just end up having to manually bubble it up and forgetting it at some point.

        You’re not advocating “explicit error handling”; you’re advocating “explicit error bubbling”. The former is good practice, the latter is downright dangerous.

        • Daniel Souza

          If you’re always dealing with errors explicitly (and in Go that often involves bubbling up errors explicitly by returning an ‘error’ upwards), then you won’t “forget it at some point” unless you explicitly forget/ignore errors (by assigning them to _ ), which you shouldn’t be doing, since everything can fail at any given time. Unless your idea of “forgetting an error” is not having your program crash terribly because of an Exception that was not handled, which is possible to happen in Go if you ignore the ‘err’ of some action. After a while, checking for errors in Go becomes a muscle reflex and forces you to think a lot more about errors and how to deal with them IMO.

          Of course this doesn’t make it any better than using Exceptions, it’s just different and yes, more verbose. There are packages too that make error handling in Go smoother (and include more annotations and stack trace information) that make error handling more sane. With that said, yes, error handling in Go is one of the few things that make me cringe in the language, but it’s not the end of the world (if you think of it as “C error handling but slightly better”).

          • robertjpayne

            Go lang seems to share the mentality of iOS Objective-C/Swift which is that errors are recoverable and exceptions are not.

            I agree with you that explicit handling is best otherwise corners are cut and errors are just left dangling.

            I see far too many catch all handlers for exceptions in all sorts of programming languages without any care as to what state the process may left in by not properly deciphering the severity of the error and managing it or actually letting your process crash.

            node.js also has no convention of when to use exceptions or errors or how to properly bubble up errors ( outside of EventEmitter ). There’s some community guidelines but good luck and have fun debugging any framework or library you use that decides to stray away from the norm.

  • robmuh

    Personally after 25 years of watching technologies come and go Node and its community have all the indicators of a failed hype language like Rails has had. So many real computer scientists and don’t-care-about-show programmers who have been afraid of being forced into node on the back end are seeing the emergence of a language that has been very carefully crafted by geniuses who know the needs of emerging applications particularly on the back end. Good programmers cloistered behind enterprise walls in particular will find interest in Go. Python programmers are moving to Go. Node programmers are moving to Go. Perl programmers are moving to Go. C/C++ programmers are moving to go. The arguably mythical creator of the Node.js Express in MEAN stack (TJ) moved to Go (and it turns out he wasn’t joking). Rather than avoid the issue of concurrency by forcing everything to be async Go allows for it while fully leveraging all scalability modern multi-core machines offer. Go was written for this server-centric focus in mind rather than cramming a front-end, ancient yet modernized language onto the server. My personal favorite part of moving to Go — especially for web services supposedly in the Node sweet spot — is being free from the horribly poorly designed NPM package manager and the we-dont-give-a-shit, lets-play-guitars-laugh-out-loud-and-stroke-our-chin-beards-to-look-smarter Node community as a whole.

    • frankel0

      I would be interested to hear what about NPM that you find to be “horrible”.

      Also, I’d love to hear what your Go web-application stack looks like and if you use any framework/MVC/whatever as your baseline. Personally, for web-based applications I find Express/Node to be wonderful, even when the background processes are in other languages such as Go. I’ve played around with the Go (http?) web packages some but found them to be a bit under-developed. While Go is certainly better for high-performance, largely parallel workloads I still see a place for Node.

      • robmuh

        For starters NPM creates dozens, perhaps even hundreds of copies of the identical modules (lodash, etc.) because its flawed base architecture assumes you have to bundle them all for every dependency to match version requirements. This, in turn, blows out the path length maximums on Windows, but is bad enough it its own right.

        Go’s `go get` and static linking make it wonderful to work with in comparison not to mention its compatibility with the huge volume of C libraries already available.

    • Andres Manz

      Good comment. Well, I still prefer C++ over everything else. And I don’t think that, to me, any other language could ever replace it. Java couldn’t (although I like it), C# couldn’t (same here) and JavaScript couldn’t (I won’t say anything about that nightmare).

      But today I finally got to look into Go. And I think it is a very nice language. I’ll be honest here: If Go *should* become the most popular language for server-side web development (which would be a good thing!), I’d be a little bit confused. Because C and C++ are everything but popular when it comes to web development, and yet I see many – quite important – similarities between C/C++ and Go.

      There are a few things I don’t like about Go. The upper case, lower case stuff, for example. If I had to pick one of the newer languages as a replacement for C++ though, it would certainly be Go. I think it has (almost) everything a good, modern language needs. Still, from what I’ve seen until now, I am not sure if that language really is necessary, because it might be *too* similar to existing languages. I’m very excited to see the future of Go.

      • robmuh

        Go is a phenomenally great language for microservices (which is the first thing we used it for). Not all server-side web development falls under that category. It is absolute bliss when you can use the same code libraries to create c-speed command-line tools that also serve up your REST or other web APIs. Only a very specific type of engineer/developer appreciates this. Those I care about do.

      • NTN

        The only language that can compete with C in speed and has C++ features like operator overloading and generics I know is Rust. It is memory safe without garbage collection and has closures, pattern matching and algebraic data types.

        I have no idea if it is a good language, I’m not good enough in it. It has a lot of tedious things. Initializing an immutable array is a pain in the ass. Making a complex data structure with pointers is nearly impossible. ( Although, usually you want to implement these with arrays anyways.)

        These problems can be solved by using unsafe features, but then the safeness guarantee goes away, so you need to be a little careful instead of just thowing code at the compiler.

    • James Dixon

      Normally, I wouldn’t reply to a comment like this, but after reading your Disqus comment history, I couldn’t help myself. In this thread, you’re crapping all over Node and its community, yet you’ve posted many comments over the past year that praise Node and how it’s better than RoR, PHP, etc. What’s the deal? In general, it just seems like the vast majority of your comments are shitting on something, whether it be Node, RoR, or some guy trying to post an informative article on Sublime 3. Maybe it’s best to keep those types of comments to yourself unless you have something constructive to say? Stay douchey.

      • robmuh

        I LOVE node v.s. *anything* in RoR or PHP (*shiver*) mostly because I have direct professional experience being burned by their flaws. I used to be pro Ruby as well (v.s. the memory-leaking PHP crap for example).

        My “douchey”-ness is mostly calling out discoveries and warnings for those interested to do the work and their own research. As much research as I do before investing mindshare in a technology I place high value on those that are not afraid to call out the bad. The rest of it is personal experience with individuals for whom I have zero respect based on reading their comments and their responses to bugs when pointed out that they choose to ignore. The Node community is full of these individuals. The Go community is not.

        By the way, have you ever heard Linus Torvalds or Steve Jobs comment about technology (or people) they disagrees with? My comments are downright tame in comparison. In fact, I take your comment as a compliment. Stay bozo.

        • emojisequence

          As a semi-newb coming from the front-end/php world, with some experience with Node/Clojure, would you pick Clojure Go or Node for an eCommerce project? Thanks

      • Richard Ellicott

        not fair, we are allowed to “shit on things” especially if they make more work

    • Richard Ellicott

      i just found go….. woah…. so like previously only python and C# have really got me excited

      i don’t think go will be standard for a long time, but taking the go tour is like being shown round the death star

      the only other thing i sorta hoped for was compiled C#

  • LOL

    I love go, but it is not a next-gen language. The same about js.

    • Richard Ellicott

      what’s a “next gen” language?

      • LOL

        Obviously language that doesn’t stuck in 1960s language design idioms.
        The really shameful example is nullable pointers and all that nil pointer dereference crap. A bit more modern approach (80s or 90s in the face of ADT) and this would not be a problem.

        • Richard Ellicott

          i will be soon out of my usual learning so no point writing an essay for me. But i did read about that and it’s along the lines of the type system, so some things can be of a different type they then don’t ==

          I think you might be being a bit harsh, Go is a serious upgrade on C++ in my personal opinion

          It needs to be “stuck in 60s design idioms” frankly doesn’t it because it is trying to be absolutely as good as C or C++

          So what you want is sort of more abstraction, I can deal with it I think

          However when they designed the language they said “it is now done” they had to do that… it’s now in a strong position to be a working language

          I think in the future I will dream of some Hybrid Language that is even easier to write and even more wasteful of memory but maintains maximum speed

          So i think you’re being harsh 🙂 Further none of us will get to use it anyway LOL, we’ll have to use C++ 🙁

          edit: all my opinion anyway, i imagine you are right

          • LOL

            ADT is a zero cost abstraction. For instance, pointer Pointer = Ref | None should have no memory overhead in comparison to C’s pointers: NULL (nil) refers to None, others are valid references.
            It is shameful to see new languages without ADT support.

            PS you may already noticed ugly solutions frequently becomes popular: C, C++, Java with its pseudo-crossplatform support, ugly javascript, horrible mess called node.js, unintuitive mess called Unix, etc.

          • Richard Ellicott

            zero cost?!

            not even the extra memory footprint or anything? Not even the size of the exe? 2.3 MB these hello world weigh in at, i try the same with g++ it is 15KB

            I agree with you if the exe is only slightly bigger but the memory requirement and speed are moreless the same?

          • LOL

            > zero cost?!

            Yes

            > not even the extra memory footprint or anything?

            Yes, for safe pointer wrapper there’s no need in additional variables other than raw pointer itself. It is a pure compiler trick exploiting the fact pointer is nil if its value is 0. Thus it can translate raw pointer into safe wrapper and back unambigously.

            > Not even the size of the exe? 2.3 MB these hello world weigh in at

            Apples vs oranges comparsion that is: static vs dynamic linking, runtime size (for instance, go runtime includes garbage collector, goroutine scheduler, wider standard tools, like strings that are not a pain to use and more), etc.

          • Richard Ellicott

            well i feel i should announce the jury is still out for me on golang

            how about this for a “60s design idiom”

            hypot := func(x, y float64) float64 {
            return math.Sqrt(x*x + y*y)
            }

            functions are values to, none of the inconsistent syntax of these things in C#!!

            are you sure this language is stuck in the past, i feel the null null issue was covered and explained (perhaps beyond me) on the faq, it looks like they have intelligent well thought out reasons (it was the type system)

            I think this language is targeted at C programmers sure but I flirted with some other languages and I want to come back to golang again

          • LOL

            > functions are values to

            Idea from 1958, LISP

            > i feel the null null issue was covered and explained

            nil pointer dereference definitely was less an issue compared to my short experience in Java (Android), but it still is. I believe though it is rather the contribution of built in asychronous primitives support than a language: Android program is a callback mess, both Go apps were servers with clean synchronous style code.

          • Richard Ellicott

            okay it’s just i am vaguely for no explicable reason convinced i like the idea of function pointers and stuff, despite the fact i have never found them useful and just well thought it was nice the syntax was so logical

            (ignore me there)

            …then the actual “nil pointer dereference”

            i guess i have never found it a practical issue this, i have yet to understand how it will be a problem for me?

            But I am convinced you’re right, clearly you are pointing out a correct logic and saying it doesn’t even cost anything.

            I just need to read more/ play more to find out why this is annoying 🙂