Зарегистрируйтесь, чтобы продолжить обучение

Структуры в срезах и картах Структуры в Go

В реальных программах редко обрабатывается одна сущность. Обычно приходится работать с множеством: список заказов, множество пользователей, каталог товаров. Чтобы хранить и организовывать такие данные, в Go есть срезы и карты. А если их элементами становятся структуры, мы получаем естественные и удобные модели.

Срезы

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

Начнем с простого: список имен пользователей.

users := []string{"Анна", "Борис", "Светлана"}
for i, name := range users {
fmt.Println(i, name)
}

Здесь []string — это срез строк. Мы видим порядок, можем обратиться к элементу по индексу (users[0] даст "Анна") и пройтись по всем в цикле.

Карты

Карта — это набор пар «ключ → значение». Мы используем ее, когда порядок не важен, а быстрый доступ по ключу критичен.

Простейший пример: справочник паролей по логину.

passwords := map[string]string{
"admin": "qwerty123",
"user": "12345",
}

fmt.Println(passwords["admin"]) // выведет qwerty123

Здесь map[string]string — это карта, где ключом выступает логин, а значением — пароль. Доступ по ключу мгновенный, перебор не нужен.

Срезы структур

Теперь усложним задачу. Представим систему заказов и определим структуру Order:

type Order struct {
    ID       int
    Customer string
    Items    []string
    Status   string
}

Создадим срез заказов:

orders := []Order{
    {ID: 101, Customer: "Иван", Items: []string{"Ноутбук", "Мышь"}, Status: "new"},
    {ID: 102, Customer: "Мария", Items: []string{"Телефон"}, Status: "processing"},
}

for _, order := range orders {
    fmt.Printf("Заказ %d для %s, статус: %s\n", order.ID, order.Customer, order.Status)
}

Все данные собраны в единую модель, нет риска рассинхронизации между отдельными срезами.

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

Чтобы быстро находить заказ по ID, используем карту:

ordersMap := map[int]Order{
    101: {ID: 101, Customer: "Иван", Items: []string{"Ноутбук", "Мышь"}, Status: "new"},
    102: {ID: 102, Customer: "Мария", Items: []string{"Телефон"}, Status: "processing"},
}

order := ordersMap[101]
fmt.Println(order.Customer) // Иван

Карта позволяет получать заказ напрямую, без перебора.

Структуры как ключи карт

Иногда сама структура может быть ключом. Например, оценки студентов по имени и возрасту:

type Student struct {
    Name string
    Age int
}

grades := map[Student]float64{
    {Name: "Ольга", Age: 20}: 4.5,
    {Name: "Петр", Age: 22}: 3.9,
}

Важно: ключ не может содержать несравнимые типы — такие как срезы или карты.

Комбинации

На практике часто встречаются вложенные варианты:

  • срез внутри структуры, которая хранится в карте;
  • карта внутри структуры, которая лежит в срезе;
  • карта, где значением является срез структур;
  • срез структур, внутри которых есть срезы.

Когда использовать

  • Срез — когда нужен порядок и обход всех элементов.
  • Карта — когда важен быстрый доступ по ключу и порядок не имеет значения.

На практике оба механизма комбинируются: срез для отображения и сортировки, карта для поиска и проверки существования.

И только когда мы соединяем структуры со срезами и картами, мы получаем мощные и гибкие модели данных. Например, список всех заказов (срез структур) или база клиентов, где каждому email соответствует карточка клиента (карта структур).


Самостоятельная работа

Небольшое задание на работу со структурами и срезами.

Задачи:

  1. Воспользуйтесь структурой Book:

    type Book struct {
        Title  string
        Author string
    }
    
  2. Создайте срез из не менее чем трёх книг.

  3. Выведите заголовки всех книг в одной строке, через запятую.

  4. Отфильтруйте книги по автору (например, "Иванов") и выведите количество таких книг.

Показать пример ответа
package main

import (
    "fmt"
    "strings"
)

type Book struct {
    Title  string
    Author string
}

func main() {
    // 2) Срез структур
    books := []Book{
        {Title: "Go для начинающих", Author: "Иванов"},
        {Title: "Алгоритмы", Author: "Петров"},
        {Title: "Советы по Go", Author: "Иванов"},
    }

    // 3) Заголовки через запятую
    titles := make([]string, 0, len(books))
    for _, b := range books {
        titles = append(titles, b.Title)
    }
    fmt.Println(strings.Join(titles, ", "))

    // 4) Фильтрация по автору
    author := "Иванов"
    count := 0
    for _, b := range books {
        if b.Author == author {
            count++
        }
    }
    fmt.Printf("Книг автора %s: %d\n", author, count)
}

Дополнительные материалы

  1. Go Blog — Slices: usage and internals
  2. Effective Go — Slices
  3. Effective Go — Maps
  4. Go Spec — Slice types
  5. Go Spec — Map types

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff