> Какие группы паттернов проектирования существуют (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Aston

Стек: Go

> Пример ответа

Короткий ответ

Выделяют три классические группы паттернов проектирования: порождающие (creational), структурные (structural) и поведенческие (behavioral). Порождающие управляют процессом создания объектов, структурные определяют композицию классов и объектов, поведенческие описывают взаимодействие и распределение ответственности между объектами. В Go часто используют упрощённые варианты из-за отсутствия наследования и наличия интерфейсов и композиции.

Подробное объяснение

Классификация из GoF (Gang of Four) остаётся базовой:

  • Порождающие - скрывают механизм инстанцирования, делают систему независимой от способа создания объектов. Примеры: singleton, factory method, abstract factory, builder, prototype. В Go вместо классического наследования применяются интерфейсы и функции-конструкторы.

  • Структурные - упрощают проектирование за счёт определения отношений между сущностями. Примеры: adapter, facade, decorator, composite, proxy. В Go часто реализуются через композицию структур и интерфейсов, а не через наследование.

  • Поведенческие - решают задачи эффективного взаимодействия между объектами, распределяют алгоритмы и ответственность. Примеры: strategy, observer, chain of responsibility, command, state. В Go активно используются функции как значения первого класса, что упрощает реализацию многих поведенческих паттернов.

Дополнительно выделяют паттерны уровня архитектуры (например, repository, unit of work, CQRS), но они не входят в классическую триаду GoF. Для Go важно понимать, что некоторые классические паттерны либо не нужны (например, singleton часто заменяют пакетом с глобальной переменной), либо реализуются идиоматично через интерфейсы и замыкания.

На практике

Для senior-позиции важно не просто перечислить группы, а показать понимание, когда паттерн оправдан, а когда - избыточен. В Go-проектах часто встречаются:

  • Порождающие: функции-конструкторы с опциями (functional options), пул объектов (sync.Pool) вместо singleton.
  • Структурные: middleware как декоратор для HTTP-обработчиков, адаптеры для работы с внешними API.
  • Поведенческие: стратегия для обработки платежей, observer через каналы и горутины, chain of responsibility в виде цепочки middleware.

Кандидат должен уметь объяснить trade-off: паттерн решает конкретную проблему, но добавляет абстракцию. В Go часто проще написать простую функцию или структуру, чем разворачивать полную реализацию паттерна из учебника.

Пример кода

Порождающий паттерн на Go - функциональные опции вместо builder:

GO
type Server struct {
host string
port int
tls bool
}
type Option func(*Server)
func WithHost(host string) Option {
return func(s *Server) { s.host = host }
}
func WithPort(port int) Option {
return func(s *Server) { s.port = port }
}
func WithTLS(tls bool) Option {
return func(s *Server) { s.tls = tls }
}
func NewServer(opts ...Option) *Server {
s := &Server{host: "localhost", port: 8080}
for _, opt := range opts {
opt(s)
}
return s
}

Поведенческий паттерн - стратегия через интерфейс:

GO
type PaymentStrategy interface {
Pay(amount float64) error
}
type CardPayment struct{}
func (CardPayment) Pay(amount float64) error {
// обработка картой
return nil
}
type CryptoPayment struct{}
func (CryptoPayment) Pay(amount float64) error {
// обработка криптой
return nil
}
type Checkout struct {
strategy PaymentStrategy
}
func (c *Checkout) SetStrategy(s PaymentStrategy) {
c.strategy = s
}
func (c *Checkout) Process(amount float64) error {
return c.strategy.Pay(amount)
}

Как отвечать на собеседовании

Начните с чёткого перечисления трёх групп и их назначения. Затем приведите по одному примеру из каждой группы, желательно на Go. Покажите, что понимаете, как особенности языка влияют на реализацию: отсутствие наследования, наличие интерфейсов, горутин и каналов. Упомяните, что в Go некоторые паттерны упрощаются или заменяются идиоматичными конструкциями. Если спросят про конкретный паттерн, объясните проблему, которую он решает, и приведите минимальный пример. Не пытайтесь перечислить все паттерны - лучше глубоко разобрать 2-3.

Что проверяет интервьюер

Интервьюер оценивает:

  • базовое знание классификации GoF;
  • умение применять паттерны в контексте Go, а не механически переносить примеры из Java или C++;
  • понимание trade-off: когда паттерн полезен, а когда создаёт лишнюю сложность;
  • способность объяснить, как идиомы Go (интерфейсы, композиция, функции как значения) влияют на реализацию;
  • умение привести релевантный пример из реальной практики.

Типичные ошибки

  • Перечисление паттернов без объяснения, какую проблему они решают.
  • Слепое копирование реализации из других языков без учёта особенностей Go.
  • Утверждение, что в Go паттерны не нужны - это крайность, паттерны полезны, но их применение должно быть осознанным.
  • Путаница между группами, например, отнесение adapter к поведенческим.
  • Излишнее усложнение ответа: для senior достаточно краткого, но точного объяснения с примерами.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью