The example in this post will demonstrate the following aspects of generics.
Using an interface to specify generic constraints;
Implementing a generic binary tree via interfaces;
Using generic in the context of callbacks;
Constraint the binary tree to work with all Go numeric types.
Specifying a customer generic constraint types
I have created a generic type as a template for all Go numeric types. The code is as follows:
Implementating the generic binary tree
In my demonstrator, I have separate the interface of my binary tree from its implementation code.
The interface of my binary tree looks like this:
In this case, I am using my customer generic type constraint NumericType specified in the package named model.
I have implemented my binary tree node based on the above interface this way:
I have also created a default node builder like this:
This builder supports the creation of defaultNodes based on a range of numeric types.
I have also created a callback type NewNode to support multiple builder types which looks like this:
I can use this call back to inject to node builder to make my generic binary tree InsertNode operations able to deal with several implementations. The code for my tree insertion looks like this:
Using the generic binary tree
Go generics is not unlike generics found in other languages such as C++ template. To use a generic, you must first instantiate with the underlying type.
You can see an example demonstrating the steps in instantiating a uint8 node here:
You will notice a very useful feature of Go generic is the compiler ability to infer types being instantiated. For example the InsertNode operation does not require explicit declaration of the underlying type uint8. It can infer from the function arguments the underlying type. This feature reduce code verbosity.
In the case of the call back function NewDefaultNode, it was necessary to instantiate with a specific type as the compiler could not infer the underlying type. We can simply instantiate the function by declaring it this way NewDefaultNode[uint8].
My view of Go generics
Based on my experience building the demonstrator, I found the syntax for declaring and instantiating generic types very easy. Admittedly, I have had the experience of using generics in other languages. So I already had the foundation to exploit this Go feature.
However, I think anyone new to generics will find it easy to use this feature. The Go tooling will guide you by flagging potential errors at compile time, thus minimising errors at runtime. The challenge, which is not specific to Go, is deciding when it is appropriate to use generics.