When implementing functional options for different types to enable easier configuration, I want to share some common options between these types.
Considering the following simple example (where name represents a common complex shared type and id and location represent differences in the types):
type A struct{
Name string
ID int
}
type OptionFuncA func(*A)
type B struct{
Name string
Location string
}
type OptionFuncB func(*B)
func NewA(options ...OptionFuncA) A {
obj := A{}
for _, option := range options {
option(&obj)
}
return obj
}
func NewB(options ...OptionFuncB) B {
obj := B{}
for _, option := range options {
option(&obj)
}
return obj
}
In this example I want to add functional options to set the name of types A and B. I can do it like that:
type OptionA struct{}
type OptionB struct{}
func (opt OptionA) WithName(name string) OptionFuncA {
return func(a *A) {
a.Name = name
}
}
func (opt OptionB) WithName(name string) OptionFuncB {
return func(b *B) {
b.Name = name
}
}
func (opt OptionA) WithID(id int) OptionFuncA {
return func(a *A) {
a.ID = id
}
}
func (opt OptionB) WithLocation(location string) OptionFuncB {
return func(b *B) {
b.Location = location
}
}
This allows me to use the code like this:
optA := OptionA{}
a := NewA(optA.WithName("A"), optA.WithID(1))
optB := OptionB{}
b := NewB(optB.WithName("B"), optB.WithLocation("location"))
I want to have type checking on the different options for type A and B, while avoiding duplication of code which is equal for different types. Since functional options require to return the fitting function type OptionFuncA and OptionFuncB for type A and B respectively, I am wondering whether a solution exists.
Alternatively, I want to define a common interface, which different OptionX types have to implement:
// Assumption: Option is the common interface
// with options for multiple types.
var _ Option = OptionA{}
var _ Option = OptionB{}
While the actual code for setting the name in this example obviously can be shared, I cannot find a solution to define a common interface for the functional options of both types. The different required return value for the functional options does not allow it from my pov.
Is it somehow possible to enforce that OptionA and OptionB have to implement some shared options, without loosing type safety for all other available options of a specific type?