Для произвольного, потенциально большого количества необязательных параметров, хорошая идиома - использовать Функциональные опции .
Для вашего типа Foobar
, сначала напишите только один конструктор:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
, где каждая опция - это функция, которая изменяет Foobar. Затем предоставьте пользователю удобные способы использования или создания стандартных параметров, например:
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
Детская площадка
Для краткости вы можете дать название типу опций ( Детская площадка ):
type OptionFoobar func(*Foobar) error
Если вам нужны обязательные параметры, добавьте их в качестве первых аргументов конструктора перед переменной options
.
Основными преимуществами Функциональных опций идиома являются:
- Ваш API может расти со временем, не нарушая существующий код, поскольку сигнатура конструктора остается неизменной, когда требуются новые опции.
- позволяет использовать вариант использования по умолчанию как самый простой: никаких аргументов вообще!
- обеспечивает точный контроль инициализации сложных значений.
Эта техника была придумана Робом Пайком , а также продемонстрирована Дейвом Чейни .