Ответ
В Go нет классических конструкторов, как в ООП-языках. Вместо них используется идиома — функция-конструктор, обычно именуемая по шаблону NewT()
, где T
— это имя типа.
1. Идиоматическая функция-конструктор NewT()
Это обычная функция, которая инкапсулирует логику создания и инициализации экземпляра типа. Она возвращает указатель на созданный тип (*T
).
Преимущества:
- Инициализация полей: Можно задать начальные значения, в том числе для неэкспортируемых (приватных) полей.
- Валидация: Можно проверить входные параметры и вернуть ошибку, если они некорректны.
- Скрытие сложности: Внутренняя структура типа может быть скрыта от пользователя.
Пример:
type Config struct {
Host string
Port int
timeout time.Duration // неэкспортируемое поле
}
func NewConfig(host string, port int) (*Config, error) {
if host == "" || port <= 0 {
return nil, errors.New("invalid host or port")
}
return &Config{
Host: host,
Port: port,
timeout: 30 * time.Second, // Установка значения по умолчанию
}, nil
}
2. Встроенная функция new(T)
new()
— это встроенная функция, которая только выделяет память для переменной типа T
, инициализирует её нулевым значением (zero value) и возвращает указатель на эту память (*T
).
Пример:
// p будет указателем на структуру Config, все поля которой
// будут иметь нулевые значения (пустая строка, 0, 0).
p := new(Config)
Выражение p := new(Config)
эквивалентно var c Config; p := &c
.
Сравнение и когда что использовать
Критерий | Функция-конструктор NewT() | Встроенная new(T) |
---|---|---|
Инициализация | Гибкая, можно задать любые значения | Только нулевые значения |
Возвращаемое значение | Обычно (*T, error) | Только *T |
Валидация | Позволяет валидировать данные | Невозможна |
Основное применение | Предпочтительный способ для создания экземпляров структур. | Используется редко, в основном для простых типов или когда нулевая структура является валидной. Чаще заменяется композитным литералом &T{} . |