Работа с несколькими массивами и итоги


1. Задача: хранение связанных данных

Проблема

Нужно хранить температуру по дням недели — два типа данных (названия дней + температуры).

Решение (на текущем этапе)

Использовать два параллельных массива с одинаковой длиной.

temperatures := [7]int{22, 24, 21, 23, 25, 26, 24}
daysOfWeek := [7]string{"Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"}

Связь: Элементы с одинаковым индексом относятся к одному дню.


2. Вывод связанных данных

fmt.Println("Температура по дням недели:")
for i := 0; i < len(temperatures); i++ {
    fmt.Printf("%s: %d°C\n", daysOfWeek[i], temperatures[i])
}

Вывод:

Пн: 22°C
Вт: 24°C
Ср: 21°C
Чт: 23°C
Пт: 25°C
Сб: 26°C
Вс: 24°C

Принцип: Один цикл обходит оба массива одновременно по индексу i.


3. Вычисление средней температуры

tempSum := 0
for i := 0; i < len(temperatures); i++ {
    tempSum += temperatures[i]
}
avgTemp := tempSum / len(temperatures)
fmt.Printf("Средняя: %d°C\n", avgTemp)

Результат:

22 + 24 + 21 + 23 + 25 + 26 + 24 = 165
165 / 7 = 23°C

4. Ограничения подхода

Проблемы параллельных массивов

  • Нужно синхронизировать длину вручную
  • При изменении одного массива легко забыть про другой
  • Нет явной связи между данными

Решение в реальных задачах

// Структура (будет изучена позже)
type DayTemp struct {
    Day  string
    Temp int
}

week := []DayTemp{
    {"Пн", 22},
    {"Вт", 24},
    // ...
}

Но пока структур нет → используем параллельные массивы.


5. Итоги: особенности массивов

❌ Недостатки

Ограничение Описание
Фиксированная длина Размер определяется при создании, нельзя изменить
Размер в типе [3]int[5]int — разные типы
Полное копирование arr2 = arr1 копирует все элементы
Нет динамики Нельзя добавить/удалить элемент

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

Сценарий Пример
Размер известен и фиксирован 7 дней недели, 12 месяцев
Гарантия размера на компиляции Буферы с точным размером
Критична производительность Размещение на стеке → быстрее
Низкоуровневая работа Сетевые пакеты, протоколы

6. Резервирование места в массиве

Задача

Данные есть только для 7 дней, но в месяце до 31 дня.

Решение

monthTemps := [31]int{}  // Все элементы = 0 по умолчанию

// Заполняем только первые 7
for i := 0; i < 7; i++ {
    monthTemps[i] = temperatures[i]
}

fmt.Printf("День 1: %d°C\n", monthTemps[0])   // 22
fmt.Printf("День 8: %d°C\n", monthTemps[7])   // 0 (не заполнен)

Плюсы: Место зарезервировано
Минусы: Расход памяти на неиспользуемые элементы


7. Производительность массивов

Размещение в памяти

Стек (stack)     →  Быстрый доступ, массивы
Куча (heap)      →  Медленнее, срезы и структуры

Почему массивы быстрее:

  • Размер известен → память выделяется сразу
  • Хранятся на стеке → меньше накладных расходов
  • Нет динамического управления памятью

8. Сравнение: массивы vs срезы

Критерий Массивы Срезы
Размер Фиксированный Динамический
Тип [5]int []int
Копирование Полное По ссылке
Добавление элементов Невозможно append()
Использование Редко Почти всегда

9. Переход к срезам (slices)

Проблемы массивов

arr := [3]int{1, 2, 3}
// Как добавить 4-й элемент? Никак!

// Нужно создать новый массив
newArr := [4]int{1, 2, 3, 4}  // Ручное копирование

Решение: срезы

slice := []int{1, 2, 3}
slice = append(slice, 4)  // Автоматическое расширение
fmt.Println(slice)  // [1 2 3 4]

Вывод: Для большинства задач используйте срезы, а не массивы.


10. Полный пример с температурой

package main

import "fmt"

func main() {
    temps := [7]int{22, 24, 21, 23, 25, 26, 24}
    days := [7]string{"Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"}
    
    // Вывод
    fmt.Println("Температура:")
    for i := 0; i < len(temps); i++ {
        fmt.Printf("%s: %d°C\n", days[i], temps[i])
    }
    
    // Средняя
    sum := 0
    for i := 0; i < len(temps); i++ {
        sum += temps[i]
    }
    avg := sum / len(temps)
    fmt.Printf("Средняя: %d°C\n", avg)
    
    // Поиск самого жаркого дня
    maxTemp := temps[0]
    maxDay := days[0]
    for i := 1; i < len(temps); i++ {
        if temps[i] > maxTemp {
            maxTemp = temps[i]
            maxDay = days[i]
        }
    }
    fmt.Printf("Самый жаркий день: %s (%d°C)\n", maxDay, maxTemp)
}

11. Итоги

Параллельные массивы — временное решение для связанных данных
Массивы → когда размер фиксирован и известен
Полное копирование → безопасно, но дорого
Стек → быстрее для массивов
Срезы — следующий шаг для динамических коллекций

Правило:

Знаю размер + не будет меняться  →  Массив
Размер неизвестен или будет расти  →  Срез

Следующая тема: Срезы (slices) — гибкая и эффективная замена массивам для большинства задач.