runtime.Goexit

If you’ve ever needed to kick off multiple goroutines from func main, you’d have probably noticed that the main goroutine isn’t likely to hang around long enough for the other goroutines to finish: package main import ( "fmt" "time" ) func main() { go run(1, "A") go run(5, "B") } func run(iter int, name string) { for i := 0; i < iter; i++ { time.Sleep(time.Second) fmt.Println(name) } } It’ll come as no surprise that this program outputs nothing and exits with an exit code of 0.

how i test endpoints

When developing a service, you’ll want to ensure that you have decent test coverage of its endpoints. I’ve seen endpoint coverage achieved in a number of ways, some interesting, some interesting and I’d like to share my method. If you’ve arrived here, you’re probably no stranger to validating input to endpoints and it’s this use case that I’ll be demonstrating here. First and foremost, I’m using table-drive tests. In the context of service testing, they allow me to make multiple, requests to a service, using similar request bodies, without changing the test code I’m using to invoke the service, or polluting my test cases with huge, largely identical code.

test tags

One of the most useful go build flags I’ve used recently is tags. Its purpose is to look at the build tags you’ve specified and use them to drive what’s sent to the compiler for compilation. The tags flag is also available to the go test command, which means you can toggle swathes of tests on and off, without having to resort to code changes such as using flag in your TestMain function or - heaven forbid - writing logic into your tests themselves.

errors and defer

The benefits of thorough testing can’t be understated, especially when it comes to anything that’s in any way magical. For a language that avoids magic, I’d consider Go’s named return values and defer pretty magical, when used together. A big assumption and a very subtle syntax oversight and this magic would have lead to a serious production issue had it not been for a test that saved the day.

gotcha iota

I ran into a curious little gotcha with Go’s iota construct today and I wanted to share it with you. Without cheating, what would you expect the following code to output? package main import "fmt" const ( one = 1 << iota two ) func main() { fmt.Println(one, two) } If you said 1 2, you’d be correct! There’s nothing fishy going on here. Now let’s suppose we need to add another constant.

httptest

Go’s httptest package provides a really simple, elegant way to test your HTTP services. It allows you to create requests to and capture the responses from anything that implements the http.Handler interface: type Handler interface { ServeHTTP(ResponseWriter, *Request) } There are many ways to acheive this and each is tested slightly different. A colleague of mine recently asked for some help testing his HTTP server and I’m hoping that this post might help others test theirs, regardless of how they’ve implemented it.

struct options

It’s important to be explicit about the dependencies in your application. If your Server struct requires access to a database, it makes sense to force consumers to provide it with the means to connect to that database during creation. Peter Bourgon’s brilliant Go best practices, six years in post makes a brilliant case for other mandatory explicit dependencies and I urge you to read it. What about optional dependencies? When starting a new application, I’m always faced with the decision of how best to manage optional dependencies.

stupid channel tricks (p2) semaphores

Semaphores are like mutexes that allow N threads to access a shared resource instead of just 1. Go’s buffered channels make creating semaphore-like behaviour a doddle. To create a semaphore that allows 10 threads to concurrently access a shared resource, its simply make(chan struct{}, 10) etc. The only thing our threads need to lock/own is an item of the buffered channel, so it makes sense to use an empty struct, as it uses zero memory.

stupid channel tricks (p1) blocking

Channels are Go’s implementation of Tony Hoare’s CSP concurrency model. Rather than reiterate the basics, I’ll dive straight into some silly channel tricks that I’ve found to be useful. Note that these examples are designed to be easy-to-follow, rather than easy-to-copy-straight-into-production. Prevent sender from blocking Sending to a full channel blocks by design. This prevents fast senders from saturating a channel (and your available memory) but it’ll penalise them by forcing them to block, instead of penalising slow readers for not keeping up.

json time.Duration

From time to time, you’ll want to serialise/deserialise a struct whose default serialisation seems counter-intuitive. Take for example, the JSON serlisation of time.Duration: json.NewEncoder(os.Stdout).Encode(time.Hour) // result: 3600000000000 I don’t event think science knows what this number is. Asking people to configure 1 hour as “3600000000000” is not only cruel, it’s asking for trouble; miss a zero and you’ve had it. A much friendlier and more natural alternative is to allow for the confguration of time.