15 вопросов
Структуры - основной способ организации данных в Go. Методы с value и pointer receiver, встраивание (embedding) вместо наследования, теги полей для JSON и других форматов.
Name string в новой структуре? 🟢 Лёгкий
▶
При создании структуры без инициализации (User{} или var u User) все поля получают zero value своего типа. Для string это "". Для int - 0, для *T - nil.
Подробнее →В Go видимость определяется регистром первой буквы. Name - экспортировано (доступно из других пакетов), name - приватное. Это касается полей, методов, функций, типов, констант и переменных.
Подробнее →Value receiver получает копию структуры - изменения полей не видны вызывающей стороне. Pointer receiver работает с оригиналом. Если хотя бы один метод имеет pointer receiver, все рекомендуется делать pointer receiver. Pointer receiver также избегает копирования больших структур.
Подробнее →В Go нет наследования. Вместо этого есть композиция через встраивание (embedding): type Dog struct { Animal }. Методы встроенного типа "продвигаются" и доступны напрямую, но это не наследование - нет полиморфизма через базовый тип.
Подробнее →Value receiver (func (s MyStruct) Method()) получает копию - изменения не сохранятся. Pointer receiver (func (s *MyStruct) Method()) получает указатель - может менять поля оригинала. Также pointer receiver эффективнее для больших структур.
Подробнее →Встраивание - объявление типа внутри структуры без имени поля: type Manager struct { Employee }. Все поля и методы Employee доступны напрямую через Manager. Это композиция, не наследование.
Подробнее →==? 🟡 Средний
▶
Структуры сравнимы, если все их поля сравнимы. Если структура содержит слайс, map или функцию - сравнение через == невозможно (ошибка компиляции). Структура из int, string, bool - сравнима.
Подробнее →json:"name,omitempty" у поля структуры? 🟡 Средний
▶
Теги - метаданные, доступные через рефлексию. json:"name" задаёт имя поля при сериализации/десериализации JSON. omitempty - пропускает поле, если оно имеет zero value (0, "", nil, false).
Подробнее →type A = int и type A int? 🟡 Средний
▶
type A = int - алиас типа (Go 1.9+), A и int - один и тот же тип, полностью взаимозаменяемы. type A int - определение нового типа, A и int несовместимы без явного приведения. На новый тип можно навешивать методы, на алиас нельзя (если базовый тип из другого пакета).
Подробнее →Point{1, 2} вместо Point{X: 1, Y: 2}? 🟡 Средний
▶
При позиционных литералах Point{1, 2} добавление нового поля (Z int) вызовет ошибку компиляции - недостаточно аргументов. С именованными Point{X: 1, Y: 2} код продолжит работать - Z получит zero value. go vet предупреждает о позиционных литералах из других пакетов.
Подробнее →Embedding продвигает поля и методы - к ним можно обращаться напрямую. Это композиция, не наследование: нет полиморфизма, нет override. При конфликте имён нужно обращаться через имя типа. Go следует принципу 'composition over inheritance'.
Подробнее →Метод внешней структуры имеет приоритет (затеняет встроенный). Встроенный метод доступен через явное обращение: outer.EmbeddedType.Method().
Подробнее →struct{}{}? 🔴 Сложный
▶
Пустая структура struct{} занимает 0 байт. Используется для signal-каналов (chan struct{}), множеств (map[string]struct{}) и маркеров. Все значения struct{} указывают на один адрес в памяти (runtime.zerobase).
Подробнее →Компилятор добавляет padding для выравнивания полей. Первый вариант: bool(1) + 7 padding + int64(8) + bool(1) + 7 padding = 24 байта. Второй: int64(8) + bool(1) + bool(1) + 6 padding = 16 байт. Порядок полей влияет на размер структуры.
Подробнее →CPU требует выравнивание данных по границам (int64 по 8 байт). Между полями добавляется padding. struct{bool; int64; bool} = 24 байта (1+7pad+8+1+7pad). struct{int64; bool; bool} = 16 байт (8+1+1+6pad). fieldalignment линтер находит неоптимальные структуры.
Подробнее →