Массив — это последовательность фиксированной длины, состоящая из элементов одного типа. Массивы используются для работы с набором элементов, количество которых не изменяется, и там, где нужно иметь набор однотипных элементов известной длины.
Представим, что у нас есть задача хранить набор значений: например, среднесуточную температуру за каждый день недели (всегда 7 дней).
Тогда здесь можно объявить массив:
Число в скобках определяет длину массива, а литерал после скобок — тип элементов.
В Go количество элементов в массиве — это часть типа, то есть массивы [3]int
и [5]int
относятся к разным типам.
Чтобы определить в коде такую переменную, компилятор выделит в памяти область, размер которой будет определяться количеством элементов, умноженным на размер элементов. Каждый элемент будет проинициализирован значением по умолчанию.
Все элементы в памяти расположатся последовательно, поэтому доступ к ним будет иметь константную сложность O(1).
Для обращения к элементам массива используются квадратные скобки []
:
В Go индексация массивов начинается с нуля, как и в большинстве других языков программирования.
Довольно часто встречается ситуация, когда при объявлении массива требуется задать значения массива сразу. В Go можно совместить объявление и инициализацию в одной конструкции.
Инициализация производится с помощью литерала массива:
Здесь указывается сначала тип массива [7]int
, а затем в фигурных скобках через запятую — элементы массива, то есть список инициализации.
Для компилятора тип массива в приоритете: если вы указали массив из семи элементов, но в списке инициализации всего три, то оставшиеся элементы будут проинициализированы значениями по умолчанию.
Компилятор следит за размером списка инициализации, и уже такую конструкцию скомпилировать не получится:
Количество элементов в массиве может быть выведено автоматически по длине списка инициализации. Для этого используется следующая конструкция:
Три точки указывают компилятору, что размер массива должен быть выведен исходя из размера списка инициализации.
Иногда возникает необходимость указать в списке инициализации только один или несколько элементов массива, а другие не трогать.
Если бы вам понадобилось указать значение среднесуточной температуры в воскресенье, код вряд ли порадовал бы своей утончённостью:
Для больших массивов это превратилось бы в нечитаемую конструкцию:
Однако в списке инициализации можно указать только нужные элементы и их индексы. Индекс и значение указываются через двоеточие.
Размер массива может быть получен встроенной функцией len
. Так как размер массива известен на этапе компиляции, то вычисление этой функции при компиляции подменяется конкретным значением.
Если попытаться обратиться к элементу массива за пределами его размера, то сработает механизм защиты памяти в Go и начнётся паника. В отличие от языка C, компилятор и рантайм Go контролируют выход за пределы массива, не позволяя обратиться к недопустимым областям памяти.
Многомерные массивы
Многомерные массивы создаются так же, как и одномерные. Каждая размерность массива указывается в отдельных квадратных скобках.
Многомерные массивы удобно представлять себе как массив массивов:
Доступ к элементам многомерного массива осуществляется через квадратные скобки:
Обход значений массива
Для работы с массивами часто используются циклы. Например, когда нужно посчитать среднюю температуру (округлённо) в течение недели:
Здесь вводится дополнительная переменная i
, которая увеличивается на каждом шаге. В Go есть более удобная конструкция for range
, которая позволяет обойти элементы массива последовательно, не используя дополнительные переменные:
Оператор range
на каждой итерации возвращает индекс и значение следующего элемента в массиве.
Note
Обратите внимание на следующий важный момент: конструкция
_, temp := range weekTemp
создаёт новую переменнуюtemp
, тип которой будет определяться типом элемента массива.
Этой переменной на каждой итерации цикла будет присваиваться следующее значение из массива. Если изменить значение переменной temp
, то это не повлияет на значения в массиве.
Чтобы получить доступ к элементу массива, понадобится индекс:
Переменные массивов можно присваивать друг другу, однако у них должен быть одинаковый тип, причём количество и тип элементов должны совпадать.
В процессе присваивания выполняется полное копирование массива, и если программа обрабатывает достаточно большие массивы данных, то эти копирования могут существенно замедлить работу программы и увеличить потребление памяти.
Передача массива (как и переменной любого другого типа) в функцию — это копирование его значения в переменную аргумента функции. Здесь тоже будет полное копирование.
Note
С циклом
for — range
связан ещё один важный момент — операндrange
копируется во временную переменную, которая уже используется для обхода.
Это также может замедлить выполнение программы для массивов, поэтому следует использовать взятие указателя, чтобы не простаивать:
Преимущества применения массивов
- Элементы массива всегда располагаются в памяти последовательно, этому радуется процессор и ускоряет выполнение программы.
- Массивы имеют фиксированную длину, поэтому выделение памяти под массив происходит ровно один раз в момент его объявления.
- Время доступа к элементам массива минимальное.
- Go проверяет выход за пределы массива на этапе компиляции, если может вычислить значение индекса элемента на этапе компиляции, и во время исполнения программы. В первом случае будет ошибка компиляции, а во втором — паника. Панику лучше не допускать.
Недостатки применения массивов
- Массивы могут быть только фиксированной длины: если количество элементов нам заранее неизвестно, память придётся выделять с запасом.
- Массивы передаются и присваиваются с полным копированием элементов, что грозит внезапным ухудшением производительности и увеличенным расходом памяти.
- Для обработки массивов разных габаритов придётся писать разные функции (если не используются дженерики).
Массивы следует применять крайне обдуманно, когда размеры вашего массива точно известны на этапе компиляции. Это позволяет ускорить работу программы.
Чтобы исправить недостатки массивов, в Go введены слайсы, которые будут рассмотрены ниже.
📂 Go | Последнее изменение: 17.08.2024 22:10