Say I have a localised struct called MyStruct
with the following body:
struct MyStruct {
myField1 string
myField2 string
myField3 string
...
myFieldN string
}
And a function which instantiates new MyStruct
s for external callers:
func NewMyStruct(myField1, myField2, myField3, ..., myFieldN string) MyStruct {
return MyStruct{
myField1: myField1,
myField2: myField2,
myField3: myField3,
...
myFieldN: myFieldN,
}
}
Question: How would I best deal with the scenario of there being just too many fields within the struct resulting in a NewMyStruct(...
function with way too many parameters? Is there any best practice to mitigate this issue? As of now, I have several functions like this in my codebase:
func NewSuperStruct(myField1, myField2, myField3, myField4, myField5, myField6, myField7, myField8, myField9, myField10, myField11, myField12, myField13, myField14, myField15, myField16, myField17, myField18, myField19, myField20, myField21, myField22) ...
But it's not necessarily that the structs themselves are nonsensical in the sense that the properties/fields don't belong within, in my application they do make sense, the structs are just too large, that's all.
CodePudding user response:
Personally (obviously depending on the goal of the struct) I am a big fan of functional options:
type MyStructOpts func(*MyStruct)
func WithField1(field1 string) MyStructOps {
return func(m *MyStruct) {
m.myField1 = field1
}
}
func New(opts ...MyStructOpts) *MyStruct {
m := MyStruct{
myField1: "someDefaultIfneeded",
}
for _, opt := range opts {
opt(&m)
}
return &m
}
which can be used as follows:
New(
WithField1("someString"),
...
)
This has a couple of benefits:
- Callers of new do not need to worry about the order
- Passing values is explicit with field name, which means you won't mix up Field1 & Field2
- You have the ability to pass different defaults to
MyStruct
in case callers don't passWithField1
- Adding more fields doesn't lead to having to update all callers of
New
CodePudding user response:
I'd say just don't have the New
func:
struct MyStruct {
myField1 string
myField2 string
myField3 string
}
val := MyStruct{
myField1: "one",
myField2: "two",
myField3: "three",
}