I’ve been (re)learning Go recently. It has been more than six years since I did anything close to professional coding using Go. Things have changed a bit in the interim.

During this process, I’ve noticed an interesting behavior. While I am reading docs, I’m just as frequently reading source code–and mostly test code.

For the last 10+ years, I’ve worked primarily in Python. During that time, I relied heavily on the Requests library for making HTTP requests and doing “stuff” with the responses. While working on a personal project recently, I had a similar need in some Go code. I started looking around for the Go equivalent of Requests. Turns out, there is go-resty.

I started with the README in the go-resty Github repo. It seemed straightforward enough. I was looking for something simple, like this:

  • Connect to a remote API
  • Get all the objects of a particular resource
  • Iterate over them and print them out to the console

Using Requests in Python, it would be something along the lines of:

import requests

headers = {"Content-Type": "application/json"}
resp = requests.get("https://foo.example.com/objects", headers=headers)
if resp.status_code != requests.codes.ok:
    # handle non-2XX responses
    return

# handle 2XX responses
if resp.headers["content-type"] == "application/json":
    # handle JSON response
else:
    # raise an exception
    raise WrongContentError("Content-Type was not application/json")

return

With Go and go-resty, it was similar:

import "github.com/go-resty/resty/v2"

client := resty.New()
client.Header.Add("Content-Type": "application/json")
resp, err := client.R().Get("https://foo.example.com/objects")
if err != nil {
    // handle err
}

if resp.Header.Get("Content-Type") == "application/json" {
    // do stuff
}

But, I noticed that my code wasn’t entering the second if block. After scratching my head for a few minutes, I decided to see if the source code had any tests that would demonstrate how to do what I wanted. And, sure enough, there were such tests.

First, I wanted to check if my calling resp.Header.Get() was wrong. Here is a similar call in go-resty’s client_test.go file:

assertEqual(t, "application/json; charset=utf-8", client.Header.Get(hdrContentTypeKey))

Next, I ran go-testy’s test suite to see if the above test passed. Indeed, it did. So my code looked correct. After more head scratching, I looked at the source for the API I was calling (it was my own code and it was running locally). Aha! My server code wasn’t explicitly setting the Content-Type in its response and was defaulting to application/text.

This is just one example of how I’ve used tests as documentation, but it has become my default for working with third-party codebases.