How to organise a Go HTTP service
Go Shell Makefile
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.circleci
hooks
httpd
store
.gitignore
LICENSE
README.md
gofmt.sh
main.go

README.md

go-httpd Circle CI GoDoc Go Report Card

go-httpd is an example Go project, showing you how to organise that most basic of systems -- a HTTP server that allows you to set and get values in a key-value store. Trivial Hello, World programs don't demonstrate how to organise a real program, but go-httpd does. It also exhibits many other important principles of a good Go project.

Project layout

main.go, within the main package, is the entry point for the program, and this source file is at the top level of the tree.

There are other possible paths for this main package, depending on your requirements. One other suggested place is in cmd/go-httpd/. This can be convenient if your project builds more than one binary -- a CLI for example. Then the CLI can be located in cmd/go-http-cli. Two examples of projects using this structure are rqlite and InfluxDB.

Otherwise the remainder of the project is contained in two sub-packages -- http and store.

Project name

It's best not to call your project go-<something>. Just call it <something>. I called this project go-httpd to make the connection with Go clear.

Running go-httpd

Building go-httpd requires Go 1.5 or later. gvm is a great tool for installing and managing your versions of Go.

Starting and running go-httpd is easy. Download and build it like so:

mkdir go-httpd # Or any directory of your choice
cd go-httpd/
export GOPATH=$PWD
go get github.com/otoolep/go-httpd

Some people consider using a distinct GOPATH environment variable for each project doing it wrong. In practise I, and many other Go programmers, find this actually most convenient.

Run it like so:

$GOPATH/bin/go-httpd

You can now set a key and read its value back as follows:

curl -XPOST localhost:8080/key -d '{"user1": "batman"}'
curl -XGET localhost:8080/key/user1

Building and rebuilding

Once you've downloaded the code from GitHub, you'll probably want to change the code and rebuild it. The easiest way to do this is to execute the following commands:

cd $GOPATH/src/github.com/otoolep/go-httpd
go build
./go-httpd

To build and install the binary in $GOPATH/bin, instead execute go install.

Development environments

vim has good support for Go, via a plugin. Go support for Sublime 3 is also available via GoSublime.

Use the standard library

Go comes with a high-quality standard library, with support for much important functionality such as networking, compression, JSON serialization, encryption, IO, concurrency, and synchronization. It is better to use the standard library even if it means having to write a little bit of extra code, than to import a third-party library. You can learn more about this philosophy here.

You can see this principle at work in go-httpd. It uses the standard logging package, testing package, and does its own HTTP routing, even though there are literally hundreds of non-standard packages that claim to do a better job in each area. In my experience just stick with the standard library if at all possible.

Logging

Each package prefixes its log output with an identifiable string, and sends the output to stderr. Many operators find this most convenient, as they can then decide where to send the log output of your program.

Testing

Each package is tested via the framework that comes with the standard library, using simple test cases. A full test suite would involve many more tests.

To run the test suite execute the following command:

cd $GOPATH/src/github.com/otoolep/go-httpd
go test -v ./...

Interfaces

Interfaces are a key concept within Go, and allow components to interact in a very natural way. The io.Reader and io.Writer interfaces are the most important examples in the standard library.

Interfaces are also very useful for testing. The HTTP service within go-httpd does not import the Store directly, but instead specifies the interface any Store must support. This makes it very easy to pass a mock store to the HTTP service, as part of this testing.

Documentation

The GoDoc standard is very easy to follow and results in nice, easy to read, documentation.

go-httpd is documented in the GoDoc style. The GoDoc link at the top of this file is automatically generated from the comments in the source. Check the source of the README file itself to see how to add these badges to your own projects.

Pre-commit hooks

Within the hooks directory is a git pre-commit hook. Installing this hook means that your code is checked for go fmt and go vet errors before it can even be committed. While these checks can be run manually at any time, installing them as hooks ensures you don't forget.

To install the hook execute make install from within the hooks directory.

CircleCI integration

CircleCI supports basic Go testing without any extra work on your part, but that testing can be more sophisticated. The example yml file included in this repository shows how to instruct CircleCI (version 1.0) to perform extra testing such as checking for formatting and linting issues. It also instructs CircleCI to run your code through Go's race detection system.

Go Programming References

Be sure to check out the following references:

  • The standard docs. You really don't need much else.
  • Effective Go. You should read this when you first start programming in Go, and then read it again 3 months later. And then read it again 6 months after that.
  • How to Write Go.
  • The Go Programming Language.
  • The Go Playground -- a useful place to share snippets of Go code.
  • rqlite -- a distributed database, with SQLite as its storage engine. rqlite is a much more sophisticated example of production-quality Go code, which strives to follow all the principles outlined above.
  • 400 Days of Go -- a blog post I wrote on why I like Go.