TranslateProject/sources/tech/20170322 From Node to Go A High-Level Comparison.md
2017-03-25 10:59:34 +08:00

17 KiB
Raw Blame History

From Node to Go: A High-Level Comparison

At XO Group, we primarily work with Node and Ruby to build out our system of interconnected services. We get the implicit performance benefits of Node mixed with the access to a large, established repository of packages. We also have the ability to easily break out plugins and modules that can be published and reused across the company. This greatly increases developer efficiency and allows us to make scalable and reliable applications in a short amount of time. Furthermore, the large Node community makes it easy for our engineers to contribute open source software (see BunnyBus or Felicity).

Although a good portion of my college days and early career was spent using strict compiled languages, like C++ and C#, I eventually shifted to using Javascript. While I love the freedom and flexibility, I recently found myself nostalgic for static and structured languages. Thats when a coworker turned my attention to Go.

Coming from Javascript, there are some similarities between the two languages. Both are very fast, fairly easy to learn, have an expressive syntax, and a niche in the development community. There isnt a perfect programming language and you should always choose a language that fits the project at hand; In this post, I will attempt to illustrate some of the key differences between the two languages at a high level and hopefully encourage anyone new to Go to give it a ̶g̶o̶ chance.


General Differences

Before we dive into specifics, we should understand some important distinctions between the two languages.

Go, or Golang, is a free, open-source programming language created by Google in 2007. It was designed to be fast and simple. Go is compiled down into machine code, which is where its speed is derived from. Debugging is fairly easy with a compiled language because you are able to catch a large chunk of errors early on. It is also a strongly typed language which helps with data integrity and finding type errors at compile time.

Javascript, on the other hand, is a loosely-typed language. Aside from the added burden of data validation and “truthy” evaluation pitfalls, using a loosely-typed language can can have its own benefits. There is no need for interfaces or generics and currying/flexible arity make functions extremely versatile. Javascript is interpreted at runtime, which can lead to issues with error handling and debugging. Node is a Javascript runtime built on Googles V8 virtual machine making it a lightweight and fast platform for web development.


Syntax

Coming from Javascript, Gos simple and intuitive syntax was very inviting. Since both languages syntaxes are said to have evolved from C, there is quite a bit of overlap. Go is commonly referred to as an easy language to learn. This is due to the developer-friendly tools, pared-down syntax, and opinionated conventions.

Go has a number of built-in features that make development a bit easier. The standard Go build tool lets you compile your code down into a binary file or executable with the go build command. Running tests with the built-in test suite are as simple as calling go test. Things like natively-supported concurrency are even available at the language level.

According to the Go developers at Google, programming today is too complicated with too much “book keeping, repetition, and clerical work.” This is why the Gos syntax was designed to be clean and simple in order to reduce clutter, increase efficiency, and improve readability. It also encourages developers to write explicit, easy to understand code. As a result, Go only has 25 unique keywords and one type of loop (for-loop) as opposed to ~84 keywords (reserved words, objects, properties, and methods) in Javascript.

In order to illustrate some syntactical differences and similarities, lets look at a couple of examples:

  • Punctuation: Go strips out any superfluous punctuation in order to increase efficiency and readability. Although Javascripts use of punctuation is somewhat minimal (see: Lisp) and often optional, I definitely enjoy the simplicity with Go.
// Javascript with parentheses and semicolons
for (var i = 0; i < 10; i++) {
    console.log(i);
}

Punctuation in Javascript

// Go uses minimal punctuation
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

Punctuation in Go

  • Assignment: Since Go is strongly typed, you have access type inference on initialization with the := operator to reduce stuttering, whereas Javascript declares types on runtime.
// Javascript assignment
var foo = "bar";

Assignment in Javascript

// Go assignment
var foo string //without type derivation
foo = "bar"

foo := "bar" //with type derivation

Assignment in Go

  • Exporting: In Javascript, you must explicitly export from a module. In Go, any capitalized functions will be exported.
const Bar = () => {};

module.exports = {
  Bar
}

Exporting in Javascript

// Go export
package foo //define package name
func Bar (s string) string {
    //Bar will be exported
}

Exporting in Go

  • Importing: The  required  library is necessary for importing dependencies/modules in Javascript, whereas Go utilizes the native import keyword with the import path to the package. Another distinction is that, unlike Nodes central NPM repository for packages, Go uses URLs for the import path on non-standard libraries in order to directly clone dependencies from their origin. Although this provides a simple and intuitive dependency management, versioning packages can be a bit more tedious in Go as opposed to updating the  package.json  file in Node.
// Javascript import
var foo = require('foo');
foo.bar();

Importing in Javascript

// Go import
import (
    "fmt" // part of Gos standard library
    "github.com/foo/foo" // imported directly from repository
)
foo.Bar()

Importing in Go

  • Returns: Gos multiple value returns allow for elegantly passing and handling values and errors, as well as reducing the improper passing of values by reference. In Javascript, multiple values must be returned by an array or object.
// Javascript - return multiple values
function foo() {
    return {a: 1, b: 2};
}
const { a, b } = foo();

Returns in Javascript

// Go - return multiple values
func foo() (int, int) {
    return 1, 2
}
a, b := foo()

Returns in Go

  • Errors: Go encourages catching errors often and where they occur as opposed to bubbling the error up in a callback in Node.
// Node error handling
foo('bar', function(err, data) {
    //handle error
}

Errors in Javascript

//Go error handling
foo, err := bar()
if err != nil {
    // handle error with defer, panic, recover, or log.fatal, etc...
}

Errors in Go

  • Variadic Functions: Both Go and Javascript support functions that accept a fluid number of arguments.
function foo (...args) {
    console.log(args.length);
}

foo(); // 0
foo(1, 2, 3); // 3

Variadic Function in Javascript

func foo (args ...int) {
    fmt.Println(len(args))
}

func main() {
    foo() // 0
    foo(1,2,3) // 3
}

Variadic Function in Go


Communities

Although Go and Node have their differences when it comes to which programming paradigms they enable to be easier, they both have unique and supportive followings. One area where Node outshines Go is in the sheer size of their package library and community. Node package manager (NPM), the largest package registry in the world, has over 410,000 packages growing at an alarming rate of 555 new packages per day. That number may seem staggering (and it is), however, something to keep in mind is that many of these packages are redundant and/or non-production quality. In contrast, Go has about 130,000 packages.

Module Counts for Node and Go

Although Node and Go are around the same age, Javascript is more widely usedboasting a large development and open-source community. This is of course because Node was developed for the general public with a robust package manager from the start while Go was specifically built for Google. The Spectrum ratings below show the top web development languages based on current trends.

Spectrum Ratings for top 7 web development programming languages

While Javascripts popularity seems to have stayed relatively static over recent years, Go has been trending up.

Programming language trends


Performance

What if your primary concern is speed? In this day and age, it seems performance optimizations are more important than ever. People dont like to wait for information. In fact, 40% of users will abandon your site if it takes longer than 3 seconds to load.

Node is often touted as a highly performant because of its non-blocking asynchronous I/O. Also, as I mentioned before, Node is run on Googles V8 engine which was optimized for dynamic languages. Go on the other hand was designed with speed in mind. The developers at Google achieved this by building “an expressive but lightweight type system; concurrency and garbage collection; rigid dependency specification; and so on.”

To compare the performance of Node and Go, I ran a couple of tests. These focus on the rudimentary, low-level abilities of the languages. If I had been testing something like HTTP requests or time-intensive processes, I would have used Gos language-level concurrency tools (goroutines/channels). Instead, I stuck to basic features of each language (see Concurrency in Three Flavors for a deeper look into goroutines and channels).

I also included Python in the benchmarks so we feel good about the Node and Go results no matter what.

Loop/Arithmetic

Iterating through a billion items and adding them up:

var r = 0;
for (var c = 0; c < 1000000000; c++) {
    r += c;
}

Node

package main
func main() {
    var r int
    for c := 0; c < 1000000000; c++ {
        r += c
    }
}

go

sum(xrange(1000000000))

Python

Results

The clear loser here is Python clocking in at over 7 seconds. On the other hand, both Node and Go were extremely efficient, clocking in at 900 ms and 408 ms, respectively.

Edit: As some of the comments suggest, Pythons performance could be improved. The results have been updated to reflect those changes. Also, the use of PyPy greatly improves the performance. When run using Python 3.6.1 and PyPy 3.5.7, the performance improves to 1.234 seconds, but still falls short of Go and Node.

I/O

Iterating over 1 million numbers and writing them to a file:

var fs = require('fs');
var wstream = fs.createWriteStream('node');

for (var c = 0; c < 1000000; ++c) {
  wstream.write(c.toString());
}
wstream.end();

Node

package main

import (
    "io"
    "os"
    "strconv"
)

func main() {
    file, _ := os.Create("go")
    for c := 0; c < 1000000; c++ {
        num := strconv.Itoa(c)
        io.WriteString(file, num)
    }
    file.Close()
}

go

with open("python", "a") as text_file:
    for i in range(1000000):
        text_file.write(str(i))

Python

Results

Once again, Python is third at 7.94 seconds. The gap between Node and Go is small in this test, with Node taking about 1.164 seconds and Go taking 1.477 seconds (although this includes the time it takes for the Go code to compile via go runthe compiled binary shaves off another ~200 ms).

Bubble Sort

Iterating 10 million times over a 10-item array and sorting:

const toBeSorted = [1, 3, 2, 4, 8, 6, 7, 2, 3, 0];

function bubbleSort(input) {
    var n = input.length;
    var swapped = true;
    while (swapped) {
        swapped = false;
        for (var i = 0; i < n; i++) {
            if (input[i - 1] > input [i]) {
                [input[i], input[i - 1]] = [input[i - 1], input[i]];
                swapped = true;
            }
        }
    }
}

for (var c = 0; c < 10000000; c++) {
    bubbleSort(toBeSorted);
}

Node

package main

var toBeSorted [10]int = [10]int{1, 3, 2, 4, 8, 6, 7, 2, 3, 0}

func bubbleSort(input [10]int) {
    n := len(input)
    swapped := true
    for swapped {
        swapped = false
        for i := 1; i < n; i++ {
            if input[i-1] > input[i] {
                input[i], input[i-1] = input[i-1], input[i]
                swapped = true
            }
        }
    }
}

func main() {
    for c := 0; c < 10000000; c++ {
        bubbleSort(toBeSorted)
    }
}

go

toBeSorted = [1, 3, 2, 4, 8, 6, 7, 2, 3, 0]

def bubbleSort(input):
    length = len(input)
    swapped = True

    while swapped:
        swapped = False
        for i in range(1,length):
            if input[i - 1] > input[i]:
                input[i], input[i - 1] = input[i - 1], input[i]
                swapped = True
    
for i in range(10000000):
    bubbleSort(toBeSorted)

Python

Results

As usual, Pythons performance was the poorest, completing the task at hand in about 13 seconds. Go was able to finish the task over two times faster than Node.

Verdict

Go is the clear winner in all three tests, but Node, for the most part, performs admirably. And Python was there, too. To be clear, performance isnt everything when choosing a programming language. If your application doesnt need to process high amounts data, then the differences in performance between Node and Go may be negligible. For some additional comparisons on performance, see the following:


Conclusion

This post is not to prove that one language is better than another. Every programming language has its place in the software development community for one reason or another. My intentions were to highlight the differences between Go and Node, as well as promote exposure to a new web development language. When choosing a language for a given project, there are a lot of different factors to consider including developer familiarity, cost, and practicality. I encourage a thorough low-level analysis when deciding what language is right for you.

As we have seen, there are several benefits to Go. The raw performance, simple syntax, and relatively shallow learning curve make it ideal for scalable and secure web applications. With its fast growth in adoption and community involvement, there is no reason Go cant become a prominent player in modern web development. That being said, I believe that Node is moving in the right direction to remain a powerful and useful language if implemented correctly. It has a large following and active community that makes it a simple platform for getting a web application up and running in no time.


Resources

If you are interested in learning more about Go, consider the following resources:


via: https://medium.com/xo-tech/from-node-to-go-a-high-level-comparison-56c8b717324a#.byltlz535

作者:John Stamatakos 译者:译者ID 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出