Скажем, у меня есть локализованная структура с именем MyStruct
со следующим телом:
struct MyStruct {
myField1 string
myField2 string
myField3 string
...
myFieldN string
}
И функция, которая создает новые экземпляры MyStruct
для внешних абонентов:
func NewMyStruct(myField1, myField2, myField3, ..., myFieldN string) MyStruct {
return MyStruct{
myField1: myField1,
myField2: myField2,
myField3: myField3,
...
myFieldN: myFieldN,
}
}
Вопрос: Как мне лучше всего справиться со сценарием, когда в структуре слишком много полей, что приводит к функции NewMyStruct(...
со слишком большим количеством параметров способ? Существуют ли какие-либо рекомендации по устранению этой проблемы? На данный момент в моей кодовой базе есть несколько подобных функций:
func NewSuperStruct(myField1, myField2, myField3, myField4, myField5, myField6, myField7, myField8, myField9, myField10, myField11, myField12, myField13, myField14, myField15, myField16, myField17, myField18, myField19, myField20, myField21, myField22) ...
Но не обязательно, что сами структуры бессмысленны в том смысле, что свойства/поля не принадлежат им, в моем приложении они имеют смысл, структуры слишком велики, вот и все.
Лично я (очевидно, в зависимости от цели структуры) большой поклонник функциональных опций:
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
}
который можно использовать следующим образом:
New(
WithField1("someString"),
...
)
Это имеет несколько преимуществ:
MyStruct
на случай, если вызывающие абоненты не передают WithField1
New
Я бы сказал, что у меня просто нет функции New
:
struct MyStruct {
myField1 string
myField2 string
myField3 string
}
val := MyStruct{
myField1: "one",
myField2: "two",
myField3: "three",
}
Если неэкспортируемые поля нужно установить из другого пакета, используйте какие-то опции или конфиг:
type MyStruct struct {
Exported string
unexported string
}
type MyStructOptions struct {
Exported string
Unexported string
}
func NewMyStruct(opts MyStructOptions) *MyStruct {
return &MyStruct{
Exported: opts.Exported,
unexported: opts.Unexported,
}
}
Если вам нужно инициализировать после установки значений по умолчанию, создайте метод Init()
, который выполняет настройку после того, как вы определите свои экземпляры структуры.
Вы можете экспортировать поля и установить их непосредственно в клиентском коде вместо использования функции
NewXyz
. Если неэкспортируемые поля являются обязательным требованием, вы можете объявить аналогичную структуруXyzParams
с теми же, но экспортированными полями и использовать ее в качестве единственного параметра функцииNewXyz
.