Что такое идиоматическая функция-конструктор в Go? Чем она отличается от встроенной функции new()?

Ответ

В 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{}.