Whats up,
You’ve hit a typical problem when embedding sorts in Go and wanting to keep up a fluent interface. Whereas your code technology method utilizing mirror
will definitely work, you’re proper to pause and see if there’s a less complicated, maybe extra idiomatic Go resolution.
Sadly, with out resorting to code technology, there isn’t a direct language function in Go that mechanically “lifts” and adapts the return varieties of embedded strategies to the embedding sort. The conduct you’re observing is by design: whenever you name Foo
on a *MyType
, the embedded ThirdPartyType
’s Foo
technique is executed, and it naturally returns a *ThirdPartyType
.
Nevertheless, let’s discover a few various patterns that may scale back the boilerplate, although they may not be as completely seamless as your required fluent chaining:
1. Offering Entry to the Embedded Kind:
As a substitute of attempting to power the embedded strategies to return *MyType
, you could possibly present a method to entry the underlying *ThirdPartyType
if the consumer must proceed chaining its strategies:
sort MyType struct {
*ThirdPartyType
}
func NewMyType() *MyType {
return &MyType{ThirdPartyType: NewThirdPartyType()}
}
func (mt *MyType) Bar(bar string) *MyType {
// ...
return mt
}
// Accessor for the underlying ThirdPartyType
func (mt *MyType) ThirdParty() *ThirdPartyType {
return mt.ThirdPartyType
}
// Utilization:
mt := NewMyType().Bar("bar")
mt.ThirdParty().Foo("foo").// Proceed chaining ThirdPartyType strategies
// ...
This method doesn’t provide the excellent NewMyType().Bar().Foo()
syntax, however it avoids the necessity to re-implement all of the strategies. Customers can nonetheless obtain the chaining in the event that they explicitly entry the embedded sort.
Professionals:
- No code technology wanted.
- Comparatively easy to implement.
- Avoids duplicating the logic of the
ThirdPartyType
strategies.
Cons:
- Doesn’t present the precise fluent interface you initially needed.
- Requires customers to pay attention to the embedded sort and its accessor technique.
2. Utilizing Practical Choices for Initialization:
Whereas this doesn’t handle the strategy chaining after initialization, it could possibly assist hold the initialization of MyType
concise and probably incorporate the configuration of the underlying ThirdPartyType
:
sort MyType struct {
*ThirdPartyType
// ... different fields
}
sort MyTypeOption func(*MyType)
func NewMyType(choices ...MyTypeOption) *MyType {
mt := &MyType{ThirdPartyType: NewThirdPartyType()}
for _, possibility := vary choices {
possibility(mt)
}
return mt
}
func WithFoo(foo string) MyTypeOption {
return func(mt *MyType) {
mt.Foo(foo) // Straight name the embedded technique
}
}
func WithBar(bar string) MyTypeOption {
return func(mt *MyType) {
// Logic for setting Bar on MyType
// ...
}
}
// Utilization:
mt := NewMyType(WithBar("bar"), WithFoo("foo"))
This sample is extra in regards to the preliminary setup and fewer about subsequent technique chaining of the embedded sort. Nevertheless, it’s a typical and clear method to deal with complicated object initialization in Go.
Professionals:
- Clear and readable initialization.
- Permits configuring each
MyType
and the embeddedThirdPartyType
throughout creation.
Cons:
- Doesn’t clear up the strategy chaining situation after initialization.
Contemplating Your Scenario:
Given that you’ve got round 50 strategies to probably wrap, the handbook re-implementation is certainly a big quantity of boilerplate and a upkeep burden.
Whereas the “entry the embedded sort” method is less complicated, it compromises the fluent interface you need.
Due to this fact, your concept of utilizing code technology with mirror
is probably going probably the most pragmatic method to attain the precise fluent interface you’re aiming for with out manually writing a considerable amount of repetitive code.
Earlier than diving into full code technology, you may contemplate these elements:
- Maintainability of the generated code: Make sure the technology course of is strong and simple to rerun if the
ThirdPartyType
modifications. - Readability of the generated code: When you gained’t be writing it immediately, contemplate how straightforward it will likely be to know and debug if wanted.
- Potential for a less complicated technology technique: Might you iterate by the strategies of
ThirdPartyType
utilizingmirror
and generate the wrapper strategies dynamically inside your software’s construct course of (although this may add complexity to your construct)?
In conclusion, whereas Go doesn’t supply a built-in mechanism for mechanically adapting embedded technique return sorts for fluent interfaces, your code technology concept is an affordable and sure the simplest resolution to your particular wants, given the massive variety of strategies concerned. The choice patterns supply trade-offs when it comes to fluency or require specific entry to the embedded sort.