profile picture

Parth Desai

Blog about Software engineering

Linkedin Github

© 2015. Parth Desai All rights reserved.

Design generic functions in golang

Overview

Starting from golang 1.1, it offers reflection support to do almost anything dynamically. Combine that with functional programming support, and you can write generic functions that operate on combination of any data type and function.

In this article, I will describe how to write generic functions in golang, as well as disadvantages of it, compared to static functions.

Functional Programming in Golang

Golang supports first class functions, higher-order functions, user-defined function types, function literals, closures, and multiple return values.

For scope of this article, I will demonstrate three of the above features: function literals, function types and higher order functions.

In this example, we implemented filter function, that takes two arguments, slice of integer and a function. And filter the slice using the function passed.

As you can see, we call filter function, two times with different function literals, first literal filters out odd numbers, while second removes even numbers.

But, this is not enough to write truly generic code, as you can see, we can only pass integer slice and only functions who are compatible with function type that we declared beforehand.

Enter reflection!!

Reflection in Golang

Unlike C/C++, in golang every object retains associated type information, even if it is assigned to a variable with interface{} type. This feature plays key part, while using reflection.

Reflection apis are exposed in golang, through built-in package called reflect.

Official reflect package documentation: Reflect Documentation

There are two central concepts, in context of reflect package which we need to understand before diving into the code:

With help of reflection and functional programming, we can write a generic function in go, with run-time type safety.

By run-time type safety, I mean that the types of a function’s arguments are consistent with semantics of function or else the function predictably fails at run time with a reasonable error message.

As you can see in this example, we have used Value, and Type cleverly, to check if input parameters confirms the semantics of mapping, and to construct output argument.

Word of Caution

There are certain disadvantages of using generic functions: