On working with code examples

I have been busy the whole January with a development task for one of my customers. We had settled on delivering the solution with Go, even though my experience with this programming language had been very limited. Decision had been based on of the quality aspects, that is - maintainability. My customer works daily with Go, and very sporadically with other languages. Had I delivered solution in Python, for example, it would be easy for me to deliver, but difficult for them to keep effectively working with the solution afterwards, should our relationship head south at any point in time.

One of the things about Go, that I have a love/hate relationship with is its explicity. That is usually a good thing, that the language makes me do things that I spell out literally, but sometimes it can be too much. As such, I ran across a situation, where I just want a uniq function - to weed out duplicates from a slice. In python the solution is extremely simple: create a new set from the given list, and ready - a set by definition has only unique elements in it, so built in implentation takes care of it. It seemed to me that this were not the case for Go, so I kept looking. Here’s an example implementation of the function that I had found:

func removeDuplicates(elements []int) []int {
    // Use map to record duplicates as we find them.
    encountered := map[int]bool{}
    result := []int{}

    for v := range elements {
        if encountered[elements[v]] == true {
            // Do not add duplicate.
        } else {
            // Record this element as an encountered element.
            encountered[elements[v]] = true
            // Append to result slice.
            result = append(result, elements[v])
        }
    }
    // Return the new slice.
    return result
}

I like the approach, however there are several problems with the implementation. For my use, the function will reside in its own package, so it needs to be exported. Secondly, the function does not modify the input slice, just returns a copy with no duplicates. This means that a name removeDuplicates is confusing. Additionally, it is common to use brief variable names in Go, so we’ll go about and change encountered to seen, result to res, elements to elems. It’s still not as short as some of the Go code, but it’s definitely better.

Additionally, there is a major code flow issue in the loop - proper “Go way” is to have main login in a visual line, with exceptions from it handled in nested code blocks. That means that since our main logic is in the else block, we should invert the conditional logic.

We can also make use of the fact, that Go allows named return variables, so we can skip one more line that initializes res to an empty slice.

All in all, here’s a version that - in my opinion - better represents the intent behind the function, and is more idiomatically written:

// UniqueElements returns a slice with unique elements from provided slice.
// This is a non-destructive operation.
func UniqueElements(elems []int) (res []int) {
	seen := map[int]bool{}

	for i := range elems {
		if !seen[elems[i]] {
			seen[elems[i]] = true
			res = append(res, elems[i])
		}
	}
	return
}
If you've enjoyed this content, how about