Learning Go as a Node.js Developer
In the past years, Kubernetes emerged as the go-to container scheduling and management platform. As I’d like to understand better what’s happening under the hood, I decided that I’ll learn the Go language.
In this article, I’ll summarize my learnings from a Node.js developer’s point of view. I’ll pay particular attention to:
- dependency management,
- how asynchronous operations are handled.
Let’s get to it :)
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. - golang.org
Go was created in 2009 at Google by Robert Griesemer, Rob Pike, and Ken Thompson. It is a compiled language, which comes with static types. It has a garbage collector and handles asynchronous operations in a CSP style. Go has a C-like syntax:
To install Go, follow the official setup guide: https://golang.org/doc/install.
go get is shipped with the Go language itself, while
dep is a dependency manager for Go. In npm terms, you can think of them like this: use
go get whenever you’d use
npm install -g, and use
dep for project specific dependencies.
dep, you could use
go get to install it, using:
go get -u github.com/golang/dep/cmd/dep
However, there’s a drawback to using
go get - it does not handle versions, it just grabs the head of the provided GitHub repository. This is why it is recommended that you install dep using these commands:
brew install dep
(you can read instructions for different OSs here: Go install guide)
Once you have dep installed, you can create projects using
dep init, just like you would do it with
Before start developing with Go, take some time to set up the
GOPATHenvironment variable correctly - you can use the official Go install guide as a reference.
dep will create similar files that
npm would -
Gopkg.toml to describe the project, just like
package.json in the Node.js ecosystem. The analogy for
Gopkg.lock, while instead of using the
dep puts dependencies into the
To add dependencies, you only have to run
dep ensure -add github.com/pkg/errors. After running it, it will appear both in your lock and your
- the async library,
Using them, we can easily read files from the file system:
const fs = require('fs')
Let’s see what it looks like in Go!
Let’s see what happened in the code snippet above line by line:
import- with import, you can require packages your applications are built upon, just like
func main- the entry point of our application,
ioutil.ReadFile- tries to read the file, and returns two values:
datFile1if the operations were successful,
errFile1if there was some error,
- this is your chance to handle the error, or crash the process,
fmt.Printprints merely the results to the standard output.
The example above works, but reads the files one after each other - time to go asynchronous!
For handling threads, Go has a concept called goroutines. A goroutine is a lightweight thread managed by the Go runtime - it enables you to run Go functions concurrently.
To manage/synchronize goroutines, I ended up using the errgroup package. This package provides synchronization, error propagation, and Context cancellation for groups of goroutines working on subtasks of a common task.
errgroup, we can rewrite the file reading code snippet to run concurrently this way:
In the Node.js space we have a ton of options when it comes to picking a framework for writing HTTP services - Go is no different. After some searching on Google, I chose Gin to start with.
Its interface is similar to Express or Koa, including middleware support, JSON validation and rendering:
That’s how far I’ve got for now - no production experience, yet. If you feel like that this blog post was useful, and you’d like to learn more on Go, just let me know, and I’ll keep publishing what I learn along my journey tackling the Go language.
The above content would not have been possible without following articles: