In this blog post, I will assume that you are familiar with what REST is and how it works, I will assume that you understand the basics of how HTTP handles requests and that you are familiar with the basic concepts of lower* level languages such as C, C++ etc. If not, I would suggest reading around the following topics:
- Pointers
- IO Streams
- Buffers
So, now we'll get into the big question which is "Why GoLang?".
The reason I have chosen to do this in GoLang is for several reasons, firstly it is relatively new to the scene, secondly it is blazingly fast at what it does at the network level and thirdly, I struggled when I first picked up GoLang as a language and thought it'd be good to write a few posts on how to use the language.
Setting up
The first thing that we need to do to get up and running with GoLang is to setup our environment. I would highly recommend using a Linux machine or Macintosh for this, although it is possible to build GoLang on windows.
First, we need to install Go, the way we do this is to head over to the GoLang website https://golang.org/dl/ and download the relevant binaries/tar gz file onto your machine. Then follow the instructions at https://golang.org/doc/install to learn how to install the application.
Next, we need to install dep, dep is a package that sits on top of Go and manages the dependencies for a given service[1]. By using dep we can bundle all of our dependencies into the main binary that we distribute.
To install this head over to the dep website and follow the install instructions. Although this can be done on windows, it is not supported yet.
Once we have this installed, we should install an IDE, I recommend Visual Studio Code as it has very good Go bindings, although any text based editor will work.
Building our boilerplate
So, you've installed Go and Dep, you've loaded up VS Code and you're ready, what now?
The first thing that we need to do is initialise the project, we do this by running
[jamescrocker@host ~]$ mkdir ~/go/src/todo
[jamescrocker@host ~]$ cd ~/go/src/todo
[jamescrocker@host ~/go/src/todo]$ dep init
Yep it's that easy, you've now created your first go project that is dependency managed, congratulations, now what? Well seeing as series is looking at REST interfaces, it'd be rude of me not to show you how to handle a basic GET, wouldn't it?
The code file that we need to create in the first instance is called main.go, this is the only file we will create here. We can create this by running.
[jamescrocker@host ~/go/src/todo]$ touch main.go
We then want to populate this with some content, for those who don't want to understand the code, it should look like this
package main
import (
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("Hello World")
return
})
http.ListenAndServe("0.0.0.0:3000", mux)
}
Now that we have the code we want to run it, to do this you would run
[jamescrocker@host ~/go/src/todo]$ go run *.go
And now to explain this,
package main
This tells the compiler that the file is part of the main package, this is what is required for the compilation of the binary.
import (
"net/http"
)
This tells the compiler that we want to use the http package from the Go base library, if we wanted to use a 3rd party library we would have to get this from github.
mux := http.NewServeMux()
This allows us to use server path based routing in the application.
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Write([]byte("Hello World")
return
})
This tells the mux router how to route the specified request and how to handle it.
http.ListenAndServe("0.0.0.0:3000", mux)
This listens on all interfaces on the port 3000, this also tells the server to use the mux handler for all requests.
Summary
In summary we have
- Setup an environment in which we can write Go code
- We have setup a dependency manager that allows us to install 3rd party dependencies
- We have written a basic web server that will return the words "Hello World" upon request
Come back for part 2
[1] You cannot do this for a library, it just doesn't work as you end up with mismatched versions.