My journey from Node to Go

It is no secret that I have a passion for Node, it’s the language that got me into development, and the one I most enjoy.

As a Software Developer it’s always important to expand your horizons; whether that be learning new skills or languages.


What this Article is

I’ve been meaning to embark on the journey of learning Go, A programming language created at Google in 2009, for a while. This articles intention is to document my learning curve.

How I’ll do it

Node is the language I know the best, so I decided to learn Go by doing what I know. Here’s the plan:

  • Make a simple CRUD API, in Node, to manage a list of To-Do’s.
  • Make the same API, in Go.

Some assumptions

As this isn’t a tutorial on Node, my expectation is you have some knowledge of writing Javascript and how the Express web framework works.


The Application

Before we start writing code it’s always important to plan.

What we’ll make:

  • Ability to Create a To-Do item
  • Ability to Retrieve multiple To-Do’s or just one specific To-Do
  • Ability to Update a To-Do, or multiple To-Do’s
  • Ability to Delete a To-Do, or multiple To-Do’s

What we won’t make/handle:

  • Authentication
  • Testing (I have written previous posts on this, if you want to try it)
  • Frontend (this is an exercise to learn Go after-all)

The Node App

The first step is to create a new project folder(mkdir expressApplication), initialise it (npm init -y) and then install our required packages (npm i express body-parser mongoose morgan).

Then we make the Node app. Seeing as this is not a tutorial on how to write an API using node, I am just going to provide the code below.

Note: It is not good practice to have everything in one file, but it’s good enough for this article. You’ll also have to input your Mongo connection string (.connect(mlabUri)) if you plan on running this code.


GoLang logo

The Go App

This is the part of the article where I will go into a lot more detail.

At the time of writing this paragraph I have never written a Go app, have no idea about best practices or how the language works properly.

The aim, at the end of this section, is to have a good understanding of the basics, document my learning curve and hopefully help others doing the same.

Installation

If you haven’t already, head on over to the Go Downloads page and download/install it.

One thing the installer won’t make clear is workspaces. In fact it won’t even ask you what you think about them.

Workspaces

“What the hell is a Go Workspace?” I hear you ask. The short and simple answer is it’s where all of your Go development happens.

We’re not going to change where our Workspace is (if you want to you can) so it defaults to $HOME/go. Any new projects we now start will be done inside $HOME/go/src.

If you have decided to specify a different location for your Go Workspace, you’ll need to make a src directory.

Project Setup

Now we have our workspace setup, we can create our first project. Each of our subdirectories inside the src directory will represent a separate package or command, and each will contain at least one .go file.

To get started we’ll make a simple Hello World package:

  • mkdir src/helloWorld (makes a helloWorld directory under src)
  • cd src/helloWorld
  • touch main.go (creates a blank file called main.go)

Now we have our first Go programme (main.go), we should write some code. Open the file up in a text editor and lets add the following code:

q

Nothing fancy. We’re naming our package (main), importing a package (fmt) and then using it to print “Hello World” to the console.

When you have created this file, you can run the following commands:-

  • go run main.go (runs the package)
  • go build (creates a standalone executable that you can run without the Go tool)
  • go install (same as go build, but it places the executable in the workspaces /bin directory so you can run it from anywhere in your filesystem*)
  • For this to work your PATH must include your workspaces /bin directory.

Have a play

After making the “Hello World” app, I decided to take 10 minutes to have a play around with the language to see what I could learn.

imports are relative to the src directory

If you have your helloWorld package in src/helloWorld, and you decide to create a sub-package in src/helloWord/anotherPackage, the import statement is relative to the src directory so import “helloWorld/anotherPackage”

Files in the same directory can be used as part of the same package if they have the same name

If, under the helloWorld package, you have a file main.go with the following code

package main

import "fmt"

func main() {
  fmt.Println("Hello World", privateHelperFunc())
}

And another file anotherfile.go with the following code

package main

func privateHelperFunc() int {
  return 25
}

The main.go file will have access to the privateHelperFunc function as they act as though they are part of the same package.

Private functions

Functions that start with a lowercase letter (e.g. privateHelperFunc) are private and cannot be used outside the package.

Public functions

Functions that start with a uppercase letter (e.g. PublicHelperFunc) are public and are exported for use.

Assigning imported packages an alias

When importing a package you can alias that package. In the below example, the fmt package is aliased as notfmt:

package main
import (
notfmt "fmt"
)
func main() {
notfmt.Println("Hello World")
}

Three folders

In your Go Workspace you will have three folders:

  • src (where your Go projects and source code sits)
  • bin (where your executables go when you install)
  • pkg (where packages you import compile to)

Lets make an app

Now it’s time to finally get cracking on making our application!

  • Navigate to your Go workspace (the default is ~/go)
  • Make a new directory under src (mkdir src/goApi)

goApi will be our package where we aim to replicate our Node/Express API.

Enter iris

We will be building our Go API using iris (which is the Go equivalent of Express). Note: In the middle of writing this article, I became aware of a lot of controversy around Iris. If you are planning on using this package in a live environment I implore you to do some research first.

Iris is a fast, simple yet fully featured and very efficient web framework for Go.

Before we do anything we need to install the iris package. Providing you have installed Go, you can do this using the command go get -u github.com/kataras/iris. Once you have done this it will appear under your pkg directory.

Before we get into the integration with MongoDB or creating all of our CRUD operations, it’s important we have a look at how a basic Iris server looks.

The above example sets up 5 endpoints and starts the server on port 8080. Here are some important things I learnt while putting it together:

  • A panic typically means something went unexpectedly wrong. This is basically the equivalent of throw new Error() in Node. We use app.Use(recover.New()) so our sever can handle any panics thrown by the endpoints, stopping our application from going down in flames.
  • We can use Regex expressions in route definitions. In the GET request example above we have specified that an id has to be a string that contains 10 or more numbers.
  • Ignore server closed errors. We use iris.WithoutServerError(iris.ErrServerClosed) to prevent errors showing on the console when we close (CTRL + C) our server. If we don’t include this we’ll see [ERRO] 2018/04/09 12:25 http: Server closed every time we close it.

Now let’s make our main package file (touch src/goApi/main.go).

Here we’ve made seven endpoints and we’ve connected our application to MongoDB using mgo. As mentioned at the top of this section in the middle of writing this article, I became aware of a lot of controversy around Iris. If you are planning on using this package in a live environment I implore you to do some research first.

One of the most important concepts I learnt while making this API was Pointers.

Pointers allow you to pass a reference to the memory location of a variable, rather than the value itself. This would be, in a Node.js example, like amending a primitive value to a reference value.

This Pointer article has a good explanation and examples.


Closing Thoughts

This exercise taught me a few basics about the Go language, but there is still plenty to learn.

I’ve commented most of my Golang code, rather than write explanations for each line in this article. If you have any questions/comments feel free to ask!


One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.