Writing Microservices in Go

writing-microservices-in-go-01

In Hemingway’s A Farewell to Arms, the heroic archetype Frederick Henry stated of martinis, ”I had never tasted anything so cool and clean. They made me feel civilized.” The days of Hemingway might have been absent of APIs and coding languages, but had he been around in the modern era, he would have probably said the same of Go, the unique, refreshing, future-friendly language taking the API world by storm.

Today we take a look at this trendy and unique language. By the end of this piece, we will have discussed the basic mechanics of this developer favorite — we’ll even produce a rudimentary API to show how easy it is to get running.

Go? Go Where?

The Go language — also known as “golang” — began its life in 2007, as a passion project of Robert Griesemer, Rob Pike, and Kem Thompson, then employees of Google. While the language started off as an experiment rather than as a project to replace other languages, early versions showed so much promise that the project quickly took on a life of its own.

Because the language loosely derived its syntax from C, a popular language in development communities, and added functionality through type safety, garbage collection, and a large library of packages, the language quickly took on the reputation of being user-friendly. This much-lauded and highly effective user-friendly nature quickly made Go the language of choice for hobbyist developers, and by 2009, the language entered into the public consciousness.

As development has continued, adoption of Go as a standard for frameworks has exploded. This constant development and innovation positioned Go as the language of experimentation, making it prime for future-proofing and “develop for later” approaches to the development lifecycle.

Why Go, Though?

Simply put, Go is a wonderful language that incorporates the best of two worlds. Because it was developed primarily with the C programming language in mind, many long-time developers will be intimately familiar with the methodologies and terminologies inherent in the system. These similarities are in style more than substance, however, meaning that what limitations the C derived commands and syntaxes have in their native languages are all but eliminated from Go.

While its similarities with other languages is one world of positive mention, Go has become a beast in its own right, providing many extensible and experimental feature sets for further development. Go provides a seamless system for development that removes many of the most time-intensive calculations of other languages. Included with the basic packages of golang are currency primitives, dynamic language development, and a basic Net/HTTP package for handling client/server HTTP implementations in a resource and time efficient manner. Go compiles surprisingly quick, and uses basic standard libraries and packages to do some amazing things.

Blog Post API Lifecycle

Rudimentary API – The Server

Now that we’ve heard how easy it is to implement Go, let’s construct basic snippets of code for a demonstration. Today, we’re going to be creating a very rudimentary API design to respond to a query in a specific way, utilizing the fast and lightweight RESTful style of API development.

In Go (as with most languages), your first step in building a Web API or microservice is to create a basic server. First, we need to establish which packages and services will be automatically loaded on startup.

package main

import (
  "fmt"
  "net/http"
)

In the snippet above we’ve defined a few very important things. By stating the first line, “package main”, we establish that what we’re running is an executable command (executable commands in Go always use “package main”). Secondly, we declare a few additional packages we want to utilize, specifically “fmt”, “net/http”, “log”, “html”, and “io/ioutil”. Note that while we’re not going to utilize all of these in this piece of code, it is acceptable practice to toggle them all for future development needs.

Now we need to add a few lines of code to define what it is that we want our code to do.

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Welcome, %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

We’ve added two main sections to this code, each with very important roles to play in the execution. This entire code snippet will, when run, spin up a server on port 8080 of all interfaces (to connect, we will utilize https://localhost:8080). In order to do this, we needed to define two functions.

The first function, “func handler”, utilizes the http.ResponseWriter and http.Request calls to return connection to the server with a string of text. This text, “Welcome, %!”, then utilizes the r.URL.Path[1:] string to append the connection URL to the text returned. Thus, when user “John_Smith” connects to his personal portal located at “https://localhost:8080/John_Smith”, he will receive “Hello, John_Smith!” as a response indicating his connection success.

A second function, “func main”, utilizes the http.ListenAndServe to direct all traffic to port 8080 utilizing the default handler. This handler then manages the traffic flowing into port 8080 throughout the APIs’ defined functions or routes. This allows our code to work in concert with the server, directing traffic and managing the flow of data.

Extending Usefulness

What we have now is a basic web server. It’s a very good web server, but in terms of APIs, it’s utterly useless. An API by its very definition is an interface between users and applications — this communication is necessarily a two-way street, where requests are handled and responded to with specific rules.

Now that we have a server, let’s turn it into an actual API and make it do something for us. So far, we’ve developed a basic server that can host files and data for access by clients. Let’s allow a client to request the build name, number, and date when prompted with the “about” invocation.

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Welcome, %!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/about/", about)
    http.ListenAndServe(":8080", nil)
}

type Message struct {
    Text string
}

func about (w http.ResponseWriter, r *http.Request) {

    m := Message{"Welcome to the SandovalEffect API, build v0.0.001.992, 6/22/2015 0340 UTC."}
    b, err := json.Marshal(m)

    if err != nil {
        panic(err)
    }

     w.Write(b)
}

Three parts have been appended to the bottom of our code. The first, “type Message struct”, is a structure-defining element. All data needs to be given structure through defined variables, otherwise, the data is considered to be in raw format. We have defined our structure as “Text string”, meaning that whatever data is to come will be delivered as a plain text string rather than formatted into currency, dates, or other formats.

Secondly, we’ve added a rather lengthy section which will respond to its invocation with a text string message stating “Welcome to the SandovalEffect API, build v0.0.001.992, 6/22/2015 0340 UTC.” The third addition is related to the second, and is a panic state — that is, it is the defined response when a faulty invocation is made. This chunk of code will allow https://localhost:8080/about/ to return the string above, and return an error code with logging when a fault connection or request is made.

Conclusion – Simplicity to Complexity

The golang gopher - the cool new programming language on the block

The Golang gopher – the cool new programming language on the block

What has been shown so far is incredibly simple, but it’s actually some of the most important code you’ll ever seen in golang. Go is a language that is fundamentally extensible, and if you learn a single, simple function, such as invoking a call that gives simple data, this data can then be formatted, stored, manipulated, deleted, and so forth. Something as simple as calling the “about” function could be used to reference stock numbers or store pricing, for example.

Further functionality can be founded in the standard lib for just about anything you could want to do. For instance, utilizing the “filepath.Walk” function, you can scan a filesystem and output the files at the root of a folder and display the directory structure in text form. The “gzip” function allows for compression and decompression of the gzip format specified in RFC 1952.

The “regexp” function allows for regular expression search over the contents of a system or file. For massive complexity, the “runtime” package allows for coordinate operations between the user and Go’s runtime system to control subroutines and interfaces.

Thankfully, the Go system of extensibility is rather intuitive. By utilizing a package system akin to Linux, golang largely moves past the need to build heavy and time-consuming frameworks, allowing for quicker learning, production, and implementation. This relative simplicity and resultant lower overhead has made it easier for companies and individuals to build microservices and APIs — a practice that is becoming ever more important in the modern business era.