Node.js | Go

A Tale of Two Worlds

About me

Language
Usability
Standards
Ecosystem

JavaScript/ Node.js Go
OOP?
 
Prototypical inheritance Structs, methods and interfaces
Functional?
Type System Dynamic, weak Static, strong,
some short-cuts
Memory Mgmt.
Execution Just-In-Time at runtime Compiled to binary
Concurrency Single threaded event loop Goroutines
(light-weight threads)

Functions as "first-class objects", closures, ...

Garbage Collection

Concurrency

Like, perhaps we could forget about threads entirely [...]
But within a single process, we could handle many, many requests by being completely asynchronous.

I believe strongly in this idea at the time, but over the past couple of years, I think that’s probably not the end-all and be-all idea for programming. In particular, when Go came out.

[...] the interface that they present to the user is blocking,
and I think that that’s a nicer programming model.

- Ryan Dahl, Creator of Node.js

Source: https://www.mappingthejourney.com/single-post/2017/08/31/episode-8-interview-with-ryan-dahl-creator-of-nodejs/

Concurrency in Node.js

// Callback
request('http://example.com', function (err, res, body) {
  console.log(err, body); 
});

// Promise
request({uri: 'http://example.com', json: true})
  .then(function (body) {
    console.log(body);
  })
  .catch(function (err) {
    console.log(err);
  });

// Async/Await
async func fetchExample() {
  try {
    const response = await fetch('http://example.com');
    const body = await response.json();
    console.log(body);
  } catch (err) {
    console.log(err);
  }
};
fetchExample();

Asynchronous code ...


 

... but single-threaded event loop

Concurrency in Go

res, err := http.Get("http://example.com")
if err != nil {
    fmt.Println(err)
} else {
    // ...
}

Synchronous/blocking code ...

... but mostly inside Goroutines

// Excerpt from net/http/server.go
func (srv *Server) Serve(l net.Listener) error {
    // ...
    for {
	rw, e := l.Accept()
	// ...
	c := srv.newConn(rw)
	c.setState(c.rwc, StateNew)
	go c.serve(ctx)
    }
}

Language
Usability
Standards
Ecosystem

Usability for APIs - Server Setup

const express = require('express')
const app = express()

function customAuth(req, res, next) {
  // ...
  next()
}

app.use(customAuth)

app.put('/users/:id', (req, res) => {
  // ...
})

app.listen(3000)
package main

import (
    "net/http"
    "github.com/labstack/echo"
)

func CustomAuth(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        // ...
        return next(c)
    }
}

func main() {
    e := echo.New()

    e.Use(CustomAuth)

    e.PUT("/users/:id", func(c echo.Context) error {
    	// ...
    })

    e.Start(":3000")
}

Performance

Source: www.techempower.com/benchmarks/#section=data-r16&hw=cl&test=json

* DB query value not restify but plain node.js

Usability for APIs - Parsing JSON

// JSON response from some other service

"{\"name\": \"Kathryn Janeway\",\"age\": 30,\"isAdmin\": true,\"birthday\": \"2344-05-20\"}"
user = JSON.parse(res.body);

console.log(user);
type User struct {
    Name     string     `json:"name"`
    Age      int64      `json:"age"`
    IsAdmin  bool       `json:"isAdmin"`
    Birthday string     `json:"birthday"`
}

user := User{}
json.NewDecoder(res.Body).Decode(&user)

fmt.Println(user)

Usability for APIs - Sending Requests

const options = {
  method: 'POST',
  uri: 'http://example.com',
  headers: {
    'Authorization': 'Bearer QWxhabc'
  },
  body: {foo: 'bar'},
  json: true
}

request(options, function (err, res, body) {
  console.log(err, res.statusCode, body)
})

?

Language
Usability
Standards
Ecosystem

Community

"Dictatorship"

TC39 for JavaScript

TCS for Node.js

Go Team at Google

(Russ Cox)

Governance

Go's Orthogonal Feature Set

type Rectangle struct {
    Height int
    Width  int
}

func (r Rectangle) CalcArea() int {
    return r.Height * r.Width
}

type Shape interface {
    CalcArea() int
}

Data (Struct)

Functionality (Method)

Abstraction (Interface)

Unique, simple, independent concepts

that play well together

Examples from Exercism.io

a platfrom created by Katrina Owen @kytrinyx

exercism.io/submissions/af62110dc0d44465bc68769cfa359b9d
exercism.io/submissions/bf51ddffb3ed49639e4f6f70bc13b0a9
exercism.io/submissions/e1307ba076a849769b15b0625a3d5c3d
exercism.io/submissions/21416c0b09564fd19a55a59272c2db7e
exercism.io/submissions/ec4cc44d61854d61a25a90ab427a802b
exercism.io/submissions/c9a592e400da4011b61350cc05c19f72

Go has lots of Rules/Guidelines

Starting with the compiler...

... through to guidelines

invalid operation: a + b (mismatched 
types int and int64)

cannot use m (type MyType) as type 
Stringer in assignment: MyType does not 
implement Stringer (String method has 
pointer receiver)

myVar declared and not used

imported and not used: "time"
golang.org/doc/effective_go.html
golang.org/doc/faq
github.com/golang/go/wiki
blog.golang.org
  • "packages are given lower case, single-word names"
  • "Error strings should not start with a capital letter"
  • "The first sentence [of a doc comment] should be a one-sentence summary that starts with the name being declared."
  • Test data belongs in a folder called "testdata"
  • ...

fewer features

more rules/ guidelines

less diversity in the code

fewer discussions

more time/energy for the actual work

Node.js Supplementary Material?

nodejs.org/en/docs/guides

Tooling in Go - "Batteries included"

Formatting gofmt, goimports
Linting go vet, golint
Tests go test, go cover
Documentation godoc
Performance Analysis pprof
... ...

Language
Usability
Standards
Ecosystem

Source: www.modulecounts.com

Discovery for Node.js Modules

Discovery for Go Packages

Dependency Management

1995
Birth of
JavaScript

2009
Birth of
Node.js

2018

2012

2009
Birth of

Go

2018

2016

VGO

What
to

use
?

... if speed of development is the most important thing

... if it should be hard to do something wrong

Node.js and Go public

By junedev