My New Hugo Site

  1. Bash
    1. Filters
      1. grep
      2. Sed
      3. jq
    2. Shellspec
  2. Design
  3. Architectural Patterns
    1. Systemd
    2. Message Broker
    3. JSON-RPC
  4. Go
    1. Concurrency
    2. Web Applications
    3. Compound Data
    4. Json
    5. Go vs Erlang
  5. Prolog Cookbook
  6. Documentation
    1. Hugo
      1. Go Html Template
      2. Table of Contents
    2. HTML
    3. CSS
      1. Color
      2. Style Guides
      3. Layout
    4. Mathjax
  7. Visualization
    1. D3
      1. Venn Diagrams
    2. SVG
    3. Visjs
      1. Network
  8. Data
    1. Yaml
    2. Events
      1. JSON-LD
    3. JSON
      1. jCal
    4. SQL
  9. JavaScript

Go vs Erlang

I initially learnt concurrency-oriented programming from Erlang creator Joe Armstrong’s book Programming Erlang, so am learning Go by translating Joe’s Erlang examples, and these are my notes.

-module(hello).
-export([start/0]).

start() -> io:format("Hello world~n").
package main

import (
  "fmt"
)

func main() {
  fmt.Println("Hello world")
}

The go mantra don’t communicate by sharing memory; share memory by communicating very much echoes Joe Armstrong’s philosophy: “Erlang has no mutexes, no synchronized methods, and none of the paraphernalia of shared memory programming. Processes interact by one method, and one method only, be exchanging messages. Processes share no data with other processes.”

How to structure messages

I want to keep my messaging independent of programing languages by using JSON, which unfortunately neither Erlang nor Go make simple. In his book, Armstrong included a section titled The JSON bridge introducing build-in functions maps:to_json(Map) -> Bin and maps:from_json(Bin) -> Map which unfortunatly don’t appear to have ever been included in the standard distribution, requiring third party libraries.

Messages in Erlang tend to be written using curly-bracketed tuples, which are akin to JSON square-bracketed arrays. Erlang’s OTP framework includes conventions for writing these, essentially creating two types of messages: call which expects a response, and cast which doesn’t.

I posted notes on an exercise I did to rewrite the basics of OTP as part of an online course I did, with my own attempts to replicate the listening loop and call and cast.

If the loop receives a message structured {call, From, Ref, Request} it returns to sender {reply, Ref, Reply}. If it receives {cast, Request}, it doesn’t return anything.

JSON-RPC encourages this request format for what OTP calls a call:

{
	"jsonrpc": "2.0",
	"method": "funcname",
	"params": ["Arg1", "Arg2", 3],
	"id": 1
}

What OTP refers to as cast in JSON-RPC jargon is a notification and is done by not including an id key and value.

{
	"jsonrpc": "2.0",
	"method": "funcname",
	"params": ["Arg1", "Arg2", 3]
}

If there’s no problem to a call, the response looks like:

{
	"jsonrpc": "2.0",
    "result": 42,
    "id": 1
}

If there was a problem, the response looks like:

{
	"jsonrpc": "2.0",
	"error": {
		"code": -32700,
		"message": "Parse error",
		"data": "missing dot"
	},
	"id": 1
}

The response includes either a result or an error, but not both. If the error is related to the id, a NULL valued id is returned.

Project Layout

One of the nice things about Erlang is its OTP framework which encourages a top-down approach to system design. Online book Adopting Erlang provides a nice overview.

In contrast to go where the executable is not just a compiler, but a complex tool covering commons tasks such as go run ., go fmt foo.go, go mod init example/hello etc, Erlang relies on third-party tools, a popular choice being rebar3 which among other things creates project layout directories with skeleton files.

There is a a guideline for go project layout

Something currently missing in the standard go toolset is a linter, for which I’m using revive.

systemd

A reason I’ve decided to switch from Erlang to Go is I just want an executable binary, and Go seems the quicker and simpler solution.

Running a Go binary as a systemd service

Erlang Modules vs Go Packages

The Erlang philosophy is programs are split into processes, and each process is associated with a module. A module is akin to a class in object-oriented programming, which could have several instances. So the same module could be running several times as different processes.

How to Write Go Code describes a go package as “a collection of source files in the same directory that are compiled together. Functions, types, variables, and constants defined in one source file are visible to all other source files within the same package.”

Something that initially confused me about go is there’s no equivalent of the -export([functor/arity]). statement. This is thanks to the command go run . assuming all *.go files in the given directory are part of the application and all capitalised variables in the various files are automatically exported.

This simplifies compilation, removing the need for make files or external tools such as Erlang’s rebar.

Module Name

Export Declaration

Spawning processes

Sending messages

Receiving messages