Структуры и методы
struct группирует именованные поля в один тип, а метод — это func, привязанный к типу через получатель. Вместе они дают то, как Go моделирует данные и поведение. Но Go здесь не похож на языки с классами: struct — это значение, а не объект со ссылочной идентичностью; метод — это обычная функция, у которой первый аргумент записан особым синтаксисом; а «наследования» в привычном смысле нет вовсе.
Тема разбирает это по слоям. Сначала сама struct как значение, затем метод и его получатель, затем выбор между value- и pointer-получателем (кто увидит мутацию), затем встраивание — синтаксис, который путают с наследованием, хотя это композиция, — и наконец идиома конструктора, которой Go заменяет отсутствующие конструкторы. Все примеры держат отличия от C++/Java на виду: именно их и спрашивают.
Карта темы
- Структуры —
structкак композитный тип именованных полей и, главное, как значение: присваивание и передача в функцию копируют все поля; zero value уже готов; теги полей — это просто строка дляreflect. - Методы — метод это
funcс получателем (func (c Counter) Inc()); объявляется на именованном типе того же пакета (обычноstruct); вызывается черезc.Inc(). - Указательный получатель — value-получатель работает с копией (мутация теряется), pointer-получатель
*T— с оригиналом; тип получателя определяет набор методов и удовлетворение интерфейса. - Встраивание — поле без имени
type B struct{ A }встраиваетA; поля и методыAпродвигаются вB; это композиция, а не наследование — нет полиморфизма, а собственное поле/метод затеняет встроенное. - Идиома конструктора — в Go нет конструкторов; идиома — функция
NewT(...) *T, которая валидирует и возвращает готовое значение; часто zero value пригоден и без неё.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Считать struct объектом и ждать, что b := a делит состояние | Это полная копия всех полей; чтобы мутация была видна, нужен указатель |
| Думать, что метод — это что-то отдельное от функции | Метод это func с получателем; c.Inc() это сахар над Inc(c) |
| Объявлять метод на типе из чужого пакета | Нельзя — метод объявляется только на типе своего пакета |
| Менять поле в value-получателе и ждать эффекта снаружи | Мутируется копия; для мутации оригинала нужен pointer-получатель *T |
| Называть встраивание наследованием | Это композиция с продвижением; нет подтипизации и полиморфизма, своё поле лишь затеняет встроенное |
Искать в Go конструктор или new-подобный синтаксис | Конструкторов нет; идиома — функция NewT(...); часто хватает и zero value |
Значение для собеседований
Структуры и методы — junior-фильтр на «понимает модель значений Go» против «мыслит классами из C++/Java». Сам синтаксис тривиален, но отличия спрашивают почти всегда.
Что обычно проверяют:
- Почему
struct— это значение и что именно копируется при присваивании и передаче в функцию. - Что такое метод и чем он отличается от функции, на каких типах его можно объявить.
- Когда нужен pointer-получатель и как тип получателя влияет на удовлетворение интерфейса.
- Чем встраивание отличается от наследования и почему в Go нет полиморфизма через него.
- Как Go обходится без конструкторов и когда писать
NewT, а когда хватает zero value.