Go Design Patterns: Functional Options
The Functional Options pattern is a rather elegant manner of implementing a Golang struct constructor that allows for custom default values, which means that users of the API we are implementing will only need to specify the struct attribute values that the users deem that shouldn’t take their default values.
For our example, let us consider the very simple use case where we have a package named person
containing a Person
struct, which will look like this:
|
|
Before Functional Options
To initialize such an instance of the aforementioned struct, one would usually implement a function called New
, which would take a bunch of values as parameters and return the struct with the given values, like so:
|
|
To create a new Person
, one would have to call that function and pass in every single value:
|
|
This might get cumborsome in the case where there are a lot of attributes and some of them might require more intricate knowledge of the inner workings of the package.
Functional Options Pattern
Functional options to the rescue. The idea behind this pattern is fairly simple, we will have New
become a variadic function which will accept any number of arguments of the type Option
, which we define as:
|
|
Then, for every struct attribute that should have a default value, we implement a function of the following form:
|
|
For our case, let us say we want all attributes except ID
to have default values. In that case, we’d end up with something like:
|
|
Finally, all we need is adapt our New
function to handle these other functions as parameters and to set some default values. This is simply boils down to creating the Person
struct with the default values we want and then looping over and calling the given Option
s:
|
|
Note that this method sets all attributes as optional except for the ID
of the Person
. Below is an example of initializing Person
instances with functional options:
|
|
This produces the following output:
|
|