Better Programming

Advice for programmers.

How to Write Generic Helper Functions With Go 1.18

Henry Steinhauer
Better Programming
Published in
3 min readMay 9, 2022

--

Gopher is hiking
The Gopher was drawn by Egon Elbre.

A few days ago I needed to check if an array contains a specific value. Normally this is a simple task and you can use a predefined function from the programming language itself. In Go, unfortunately, you have to create it yourself. But don’t worry. Today we’ll build a function that checks if an element exists in an array. So buckle up and let’s go.

Intro

One last thing before we begin. In our solution we need generics. Therefore, we need to use at least Golang version 1.18. Fortunately, Golang released the official version 1.18 a few weeks ago, which includes generics 🙌.

Approach

Our intention should be clear. So what is our goal? It’s pretty simple. We want a function that is passed an array and a value and returns true if the array contains the value and false if the value is missing.

Solution

One solution would be to create a function where we set the property types statically. In the function, we simply iterate over the array and see if any of the values in the array are equal to our element.

It works fine. We have only one problem with this approach. Imagine that for many arrays with different types we need to check if an array contains a value. To archive this, we need to create a new function for each type. This leads to a very verbose and duplicate code base. Fortunately for us, Golang introduced a number of different generic types a few months ago. In the next chapter, we can use one of them to make our solution a little bit more flexible.

Improvements

For our use case, we need the “comparable” generic type.
(If you want to know more about generics, I can recommend the following article.) As you can see below, we need to write the name of our generic T in brackets right after the function name and assign it the type “comparable”. We also give both arguments the type T. This way, when we call the function, we can specify which type of array and element we want to compare.

To use it, we have to make the following function call:
Contains[string](["bar", "foo"], "foo") .

The word “string” inside the brackets before the parenthesis is where we specify the type of our array and value.

Benchmark

Now we have two different solutions. One where we set the type of the two arguments in the function itself. And one where we set the type in the function call. But which solution is more performant? And is the difference noticeable?

To simplify generics, you can think of them as an easy-to-use kind of reflection. Normally, this should lead to a performance difference between these two functions. But let’s see:

go test -bench=”BenchmarkContains” -run=^# -benchtime=10000x
Benchmark tests from function
Benchmark Contains Functions

To get a more meaningful result, I decided to write table benchmark tests. The above command runs both tests 10.000 times. The result is remarkable. There are no timing issues with the generic version. You can see from the image above that both tests took pretty much the same amount of time per operation.

Final thoughts

I hope the approach to checking if an array contains a certain value was interesting and helpful. If you have another solution, something to mention or questions, it would be great if you leave it in the comments. See you soon.

PS: This is the first article of a new series I have planned. Over the next few weeks, I’ll be looking at various generic helper functions, interesting benchmarks, and useful features around the go world.

--

--

Henry Steinhauer
Henry Steinhauer

Written by Henry Steinhauer

Passionate software developer who enjoys exploring new programming languages, design patterns and frameworks.

Responses (3)