Episode #13 — Github & Jira CLI with Golang part 2: regex and error handling in Go

Stephens Xu
Fullstack Network
Published in
3 min readJun 1, 2017

--

In this session we continued to work on Gong, our CLI tool for Jira & Github.

If you haven’t heard of it before, Jira is a web base project management tool.
From our work during last session, we are able to Login to Jira from CL, store credentials on the user’s computer locally.

Now here is our next step:

Automatically create a git branch off of a ticket based on ticket name and ticket type

Basically, let’s say if a Jira ticket name looking like

build a ui for client management

And this is a feature request, we want a branch name look like this

feature/build-a-ui-for-client-management

In order to achieve this, we use a function SlugifyTitle which consumes a string and uses regex to create a slug in desired format:

package gong

import (
"regexp"
"strings"
)

func SlugifyTitle(ticketTitle string) string {
re := regexp.MustCompile("[^a-z0-9]+")

return strings.Trim(re.ReplaceAllString(strings.ToLower(ticketTitle), "-"), "-")
}

And then we can verify if our regex is valid with test suits like so

package gong

import (
. "gopkg.in/check.v1"
"testing"
)

func TestSlugger(t *testing.T) { TestingT(t) }

type SluggerSuite struct{}

var _ = Suite(&SluggerSuite{})

func (s *SluggerSuite) TestSlugCreationNormalText(c *C) {
title := "This is a fake title"
c.Assert(SlugifyTitle(title), Equals, "this-is-a-fake-title")
}

func (s *SluggerSuite) TestSlugCreationWithSpecialChars(c *C) {
secondTitle := "This &&& *** is another title"
c.Assert(SlugifyTitle(secondTitle), Equals, "this-is-another-title")
}

func (s *SluggerSuite) TestSlugCreationWithMultipleSpaces(c *C) {
title := "This is a fake title"
c.Assert(SlugifyTitle(title), Equals, "this-is-a-fake-title")
}

Since I’m such a newbie in Go, I’ve actually learned something basic but also interesting about the way Go handle’s error during this session. I’ve started to notice a repetitive pattern in Go code such as this:

...
fileLocation := loginDetails.GetLoginDetailsFileLocation()
cfg, err := ini.InsensitiveLoad(fileLocation)

if err != nil {
return LoginDetails{}, err
}

section, err := cfg.GetSection("")
if err != nil {
return LoginDetails{}, err
}

username, err := section.GetKey("username")
if err != nil {
return LoginDetails{}, err
}

password, err := section.GetKey("password")
if err != nil {
return LoginDetails{}, err
}
...

Seems like every time we call a function we’d need to explicitly write code to handle errors. This looks weird to me coming from a Ruby background. Then Avi explained to me, errors are first class citizens in Go. Errors won’t be caught in form of Exceptions and surfaced to engineers automatically, errors are always values returned by a function(either nil or a real error). In order to see what the actual error is we need to write code to explicitly return this value, otherwise Go doesn’t have an automated mechanism to catch them for us.

While I’m still trying to wrap my head around Go, and as cumbersome as this process seems to me, I can see the benefits right away. This approach forces engineers to think about possible errors and error handling almost ALL THE TIME. It slows down a bit maybe, but in the long run this might actually end up training our mindset to write better code.

Tonight we will continue to work on Gong, join us if this interest you!

--

--