Структуры в Go

Теория: Что такое структура и зачем она нужна

В языке Go одним из ключевых инструментов для работы с данными являются структуры. Если переменные позволяют хранить отдельные значения (числа, строки, булевы значения), а массивы и срезы — наборы однотипных данных, то структуры дают возможность объединять в одном месте разнородные данные, которые логически связаны между собой.

Структуры можно представить как собственные типы данных, которые мы конструируем под задачу. Они помогают упорядочивать код и делать его более читаемым и удобным в поддержке.

Пример

Представим, что нам нужно описать студента: у него есть имя, возраст, список курсов и средний балл. Если бы мы хранили все в отдельных переменных, получилось бы громоздко:

var name string
var age int
var courses []string
var gpa float64

При этом сразу видно, что все эти переменные относятся к одному объекту — студенту. Гораздо удобнее объединить их в одну структуру:

type Student struct {
	Name    string
	Age     int
	Courses []string
	GPA     float64
}

Теперь у нас появился собственный тип Student, который можно использовать в программе как единый объект.

Зачем нужны структуры

  1. Группировка данных — все, что относится к одному объекту, хранится вместе.
  2. Улучшение читаемости — названия полей отражают смысл данных.
  3. Основа для объектного подхода в Go — к структурам можно добавлять методы.
  4. Удобство работы с внешними данными — например, JSON удобно парсить в структуры.

Пример

Создадим структуру Book и используем ее в коде:

package main

import "fmt"

type Book struct {
	Title string
	Author string
	Pages int
}

func main() {
	book := Book{
		Title: "Война и мир",
		Author: "Лев Толстой",
		Pages: 1225,
	}

	fmt.Println(book.Title, "—", book.Author, "(", book.Pages, "стр.)")
}

Результат:

Война и мир — Лев Толстой (1225 стр.)

Структуры в Go — это способ объединить разные данные в один логический объект. Они позволяют описывать сущности реального мира (пользователь, книга, заказ, транзакция) и делают программы понятнее.

Как без структур

Представим, что мы описываем систему заказов. Каждый заказ должен содержать идентификатор, имя клиента, список товаров и статус. Если мы не используем структуры, нам приходится хранить данные в отдельных срезах и синхронизировать их по индексам:

func main() {
	// данные о заказах разнесены по разным срезам
	orderIDs := []int{101, 102}
	customers := []string{"Иван", "Мария"}
	items := [][]string{
		{"Ноутбук", "Мышь"},
		{"Телефон"},
	}

	statuses := []string{"new", "paid"}

	// чтобы вывести заказ, приходится помнить про индексы
	fmt.Println("Заказ:", orderIDs[0],
		"Клиент:", customers[0],
		"Товары:", items[0],
		"Статус:", statuses[0])
}

Результат:

Заказ: 101 Клиент: Иван Товары: [Ноутбук Мышь] Статус: new

Проблемы такого подхода:

  • данные одного заказа разбросаны по разным переменным,
  • любая ошибка в индексах приводит к несоответствиям,
  • добавление нового свойства (например, сумма) потребует переписывать несколько структур данных.

Как со структурами

Теперь опишем заказ как единый объект:

// Order описывает заказ
type Order struct {
	ID int
	Customer string
	Items []string
	Status string
}

func main() {
	// создаем объект заказа
	order := Order{
		ID: 101,
		Customer: "Иван",
		Items: []string{"Ноутбук", "Мышь"},
		Status: "new",
	}

	// обращаемся к полям напрямую
	fmt.Println("Заказ:", order.ID,
		"Клиент:", order.Customer,
		"Товары:", order.Items,
		"Статус:", order.Status)
}

Теперь данные связаны, ошибки с индексами мы избегаем, а при добавлении нового поля (Amount, CreatedAt) нам достаточно изменить определение структуры.

Объекты и структуры в Go

В классических объектно-ориентированных языках есть классы и объекты. В Go нет классов и наследования, но структуры позволяют описывать данные и методы для них. Экземпляр структуры можно называть объектом в широком смысле — это значение пользовательского типа, объединяющее поля. Однако формально это просто значение структуры, а не объект ООП.

Синтаксис структур и базовые практики

В Go для объявления структур используется ключевое слово struct. Оно всегда пишется после имени нового типа и открывает блок с перечнем полей. Этот синтаксис уникален для Go: структуры не объявляются через ключевые слова вроде class или record, как в других языках.

Синтаксис объявления

// общий шаблон

type <ИмяСтруктуры> struct {
Поле1 Тип1
Поле2 Тип2
}
  • type создает новый тип.
  • Имя структуры принято писать с заглавной буквы.
  • Внутри фигурных скобок перечисляются поля и их типы.

Создание экземпляра

  • Литерал структуры: u := User{Login: "alex", Password: "pwd"}
  • Пустая структура: var u User
  • Через new: u := new(User) (возвращает указатель).

Обращение к полям

func main() {
	u := User{Login: "alex"}
	fmt.Println(u.Login) // чтение
	u.Login = "alexander" // запись
}

Лучше всего придерживаться следующих правил,

  • Имя структуры отражает сущность (User, Order, Report).
  • Поля называются понятно и однозначно (CreatedAt, Status, Amount).
  • Экспортируемые поля (с заглавной буквы) видны за пределами пакета, неэкспортируемые (с маленькой) — только внутри.
  • Логически связанные поля лучше группировать во вложенные структуры.

Итоги

Структуры — пользовательские типы данных в Go. Они объединяют разнородные поля в один объект; позволяют описывать сущности предметной области; дают именованный доступ к данным; упрощают изменение модели (добавление/удаление полей происходит в одном месте). На следующих уроках мы разберем поля и их типы, указатели на структуры, методы, конструкторы, композицию, теги/JSON и сравнение структур.

Рекомендуемые программы

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845