Skip to main content
Calm Code

Getting into Golang

I've been meaning to get into Golang for a while. Having worked with PHP and Java for the longest time it felt like it was time for another tool on the proverbial tool belt.

I've started with a practical little API to track my posture while I work. I'm not going to walk you through the code. If you are so inclined you can browse it at your leisure.

What I will do is share some small things I've learned so far.

Golang is relatively easy to get started. I've setup shop in VSCode using the Go extension.

The syntax takes a bit of getting used to and the pointers and references are coming back to me.

So I'm running this API on a Raspberry Pi 3, which is a small computer with only 512MB of RAM. Sure enough I can build for ARM using env GOOS=linux GOARCH=arm GOARM=7 go build 🙌

That gives me a single binary I can copy over to my pi and run. Of course we can automate the deployment with something like Ansible. So I wrote a small playbook to do these steps.

  1. Copy the service file
  2. Copy the API app
  3. Restart the service

One thing that bugged me was if I didn't add daemon_reload: yes it didn't pickup my service file changes.

- name: Restart posture service ansible.builtin.service: name: posture state: restarted daemon_reload: yes

On the Go side I'm still not cool with the single character local variables so I've adopted single words where possible. The API doesn't do much at the moment but I've managed to extract the handler methods out of the router. Most of the Gin examples don't use this convention but it looks nicer to me.

The second thing that bugged me was there was no example test for the HTTP POST method on the Gin website. I had to look around to figure out the following.

func TestCreate(t *testing.T) { router := setupRouter()

rec := httptest.NewRecorder() data := url.Values{"posture": {"sit"}} buffer := bytes.NewBufferString(data.Encode()) req, _ := http.NewRequest(http.MethodPost, "/", buffer) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") router.ServeHTTP(rec, req)

assert.Equal(t, http.StatusCreated, rec.Code) assert.Equal(t, "Created posture=sit", rec.Body.String()) }

Without that content type header the form values didn't come across.

Before I setup this repo I tried out Echo which did what I wanted but I couldn't find a way to test POSTs again, so I went with Gin which looked more mature and had more examples floating around.