Как работать с длинными списками параметров в функциях `New(...`)

Скажем, у меня есть локализованная структура с именем 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) ...

Но не обязательно, что сами структуры бессмысленны в том смысле, что свойства/поля не принадлежат им, в моем приложении они имеют смысл, структуры слишком велики, вот и все.

Вы можете экспортировать поля и установить их непосредственно в клиентском коде вместо использования функции NewXyz. Если неэкспортируемые поля являются обязательным требованием, вы можете объявить аналогичную структуру XyzParams с теми же, но экспортированными полями и использовать ее в качестве единственного параметра функции NewXyz.

mkopriva 17.03.2022 15:44
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
2
1
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Лично я (очевидно, в зависимости от цели структуры) большой поклонник функциональных опций:

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"),
  ...
)

Это имеет несколько преимуществ:

  • Абонентам новых не нужно беспокоиться о порядке
  • Передача значений является явной с именем поля, что означает, что вы не перепутаете Field1 и Field2.
  • У вас есть возможность передавать различные значения по умолчанию 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(), который выполняет настройку после того, как вы определите свои экземпляры структуры.

Daniel Farrell 17.03.2022 17:32

Другие вопросы по теме