Struct
Тема дорожной карты · Golang
Структуры в Go — составные типы, группирующие именованные поля разных типов в единое целое и служащие основным механизмом Go для моделирования доменных объектов — пользователей, HTTP-запросов, строк базы данных — при отсутствии классов. Структура определяется через type User struct { ID int; Name string; Email string }, а экземпляры создаются с помощью литералов User{ID: 1, Name: "Alice"} или new(User) при необходимости указателя. Структуры в Go удовлетворяют интерфейсам неявно: структура, предоставляющая все методы http.Handler или пользовательского интерфейса Repository, удовлетворяет ему без явного объявления, что обеспечивает внедрение зависимостей и тестируемость с mock-объектами. Теги полей вроде json:"name,omitempty", db:"user_id" и validate:"required,email" аннотируют структуры для маршалинга JSON через encoding/json, сканирования SQL через sqlx или pgx и валидации входных данных через go-playground/validator. Встраивание структур — размещение одного типа структуры внутри другого без имени поля — обеспечивает форму композиции в Go и широко используется в фреймворках Gin и Echo для расширения базовых типов вроде gin.Context или строителей цепочек middleware.
Как это работает
Struct покрывает встроенное: массивы (фиксированный размер — редко в идиоматичном Go), slices (динамические массивы — рабочая лошадка), maps (map[K]V, на хешах), strings (UTF-8 байтовые последовательности, неизменяемые). Struct — пользовательские типы с именованными полями; методы на типах (func (r Receiver) Method()); интерфейсы декларируют наборы методов (удовлетворяются неявно — нет ключевого слова implements). Указатели через & и *; slices и maps уже содержат указатели внутри.
Когда применять
Slices везде, где массивы соблазняют — почти всегда правильный ответ. Map — для lookup по ключу; помните, что Go-map не упорядочены. Embedding struct — для композиции (нет эквивалента наследования). Маленькие интерфейсы (1-3 метода) — Go-интерфейсы лучше когда обнаружены, чем объявлены (выносите, когда есть 2+ реализаций).
Типичные ошибки
Ловушки Struct: slice-граблик — append(s, x) может или не может делить underlying массив с s (при реалокации не делит — тихие баги); for _, v := range slice { go func() { use(v) }() } захватывает v по ссылке до 1.22 (closures видят последнее значение — починено в 1.22, но многие туториалы до этого); nil-maps паникуют на запись (make(map[K]V)); огромные interface-типы убивают идиому "implicitly satisfied".