Как работают встраиваемые структуры (embedding) в Go
Что проверяют
Понимаете ли вы, что встраивание это композиция с продвижением полей и методов, а не наследование. Следом обычно спрашивают, реализует ли структура интерфейс через встроенный тип и что будет при совпадении имён.
Как отвечать
Встраивание это поле без имени: type Person struct { Address; Name string }. Имя поля совпадает с именем типа, так что встроенное значение доступно как p.Address.
- продвижение: поля и методы встроенного типа доступны напрямую,
p.Cityиp.Validate(). Это синтаксический сахар, компилятор сам подставляетp.Address.City; - нет виртуальности: продвинутый метод получает в качестве получателя
Address, а неPerson. Если внутриAddress.Describe()вызываетсяa.Label(), выполнится методAddress, даже если уPersonесть свойLabel(); - наборы методов: при встраивании
Tметоды с получателемTесть и уS, и у*S, а методы с получателем*Tтолько у*S. При встраивании*Tоба набора получают всё. Отсюда вопрос, реализует ли интерфейс значение или только указатель; - интерфейсы: встроенный тип может сделать внешнюю структуру реализацией интерфейса. Интерфейсы встраиваются и в интерфейсы (
io.ReadWriterсобран изio.Readerиio.Writer), и в структуры, это частый приём в тестах, когда нужно переопределить один метод из десяти; - совпадение имён: имя на меньшей глубине скрывает более глубокое, поле
Person.CityперекроетAddress.City. Два одинаковых имени на одной глубине допустимы, пока к ним не обратиться: обращение не скомпилируется; encoding/json: поля встроенной структуры без собственного тега попадают в JSON на верхний уровень, как будто объявлены во внешней.
Где спотыкаются
Называют встраивание наследованием и ждут переопределения, как в Java. Методы встроенного типа ничего не знают о внешней структуре.
Встраивают sync.Mutex в экспортируемый тип: Lock и Unlock становятся частью его публичного API. Лучше именованное поле mu sync.Mutex, а копирование структуры с мьютексом поймает go vet.
Встраивают интерфейс в структуру и не присваивают ему значение. Вызов метода, который структура сама не реализовала, падает с паникой из-за nil.