Структуры в Go
Теория: Встраивание структур
В Go структуры часто становятся основным способом описывать данные и сущности программы. Но иногда хочется не просто описать поля, а взять готовую структуру и встроить ее внутрь другой, чтобы использовать ее как часть новой сущности. Это называется встраивание структур (struct embedding).
Простая аналогия
Представим, что у нас есть паспорт. Паспорт содержит поля: номер, серия, дата выдачи. Но паспорт всегда связан с человеком. Вместо того чтобы каждый раз описывать эти поля у человека, мы можем сказать: у человека есть паспорт и встроить структуру Passport внутрь структуры Person.
Базовый пример
Начнем с простого кода:
Здесь видно, что у Person нет явных полей Number и Issued, но так как у него встроена структура Passport, мы можем обращаться к этим полям как будто они у Person.
Это и есть главное удобство — доступ к полям вложенной структуры становится прямым, без лишнего кода.
Когда встраивание помогает
Чаще всего встраивание используют для того, чтобы расширять существующие структуры.
Например, у нас есть структура User, описывающая пользователя в системе. Для администратора хочется добавить права доступа, но не дублировать все заново.
Здесь Admin — это как будто «расширенный User». Мы не повторяем поля, а встраиваем User.
Встраивание и методы
Фишка в том, что вместе с полями встраиваемой структуры "подтягиваются" и ее методы.
Так можно "наследовать" поведение от другой структуры. Это похоже на наследование в ООП, но в Go нет классов и строгой иерархии, поэтому это скорее композиция с бонусом доступа к методам.
Что делать, если имена совпадают?
Иногда у встраиваемой структуры и у внешней есть одинаковые поля или методы. Тогда возникает "конфликт".
Внешние поля всегда приоритетнее. Чтобы обратиться к полям или методам вложенной структуры, используем явное указание (e.Base.Name).
Когда лучше не использовать встраивание
Хотя встраивание очень удобно, оно может запутывать. Представь структуру с 3–4 встроенными типами, у которых еще и совпадающие методы. Понять, откуда вызвался метод, становится сложно.
Лучше использовать встраивание, когда:
- это реально общая часть, которую удобно расширять,
- количество встроенных структур небольшое,
- нет риска сильных конфликтов имен.
Если же нужно просто "составить" объект из частей, без магии доступа к методам и полям напрямую, часто лучше сделать обычное поле:
Так код более явный, и читатель сразу понимает, что у машины есть двигатель, а не что двигатель сам по себе "живет" внутри машины.
Встраивание структур в Go — это удобный способ собирать сложные сущности из простых деталей. Оно помогает:
- расширять структуры без дублей кода,
- автоматически получать доступ к методам и полям встроенных типов,
- строить более гибкую и компактную архитектуру.
Но у этого подхода есть обратная сторона. Если переборщить со встраиваниями, код становится туманным: непонятно, откуда взялось, то или иное поле, или метод. В таких случаях лучше остановиться и сделать обычное явное поле.
Главное правило: встраивание хорошо там, где оно делает код чище и короче, а не запутаннее.


