Home > database >  How to deal with long parameter lists in `New(...` functions
How to deal with long parameter lists in `New(...` functions

Time:03-17

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 MyStructs 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 pass WithField1
  • 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",
}
  •  Tags:  
  • go
  • Related