После изучения данного урока вы сможете:
- Объявлять и инициализировать массивы;
- Присваивать и получать доступ к элементам массива;
- Итерировать элементы массива.
Массивом называют упорядоченный набор элементов фиксированной длины. В данном уроке массивы будут использоваться для хранения названий планет и карликовых планет нашей солнечной системы, но вы можете использоваться любые данные по собственному желанию.
![](https://golangify.com/wp-content/uploads/2020/04/go-read.png)
Рекомендуем вам супер TELEGRAM канал по Golang где собраны все материалы для качественного изучения языка. Удивите всех своими знаниями на собеседовании! 😎
Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.
Содержание статьи
- Объявление массива и получение доступа к его элементам
- Диапазон значений массива в Golang
- Инициализация массивов через композитные литералы в Go
- Итерация через массивы в Go
- Копирование массивов в Golang
- Массивы из массивов в Golang
Быть может, вы что-то коллекционируете? Или собирали что-то в детстве? Марки, монеты, наклейки, книги, туфли, медали, диски или что-то еще?
Массивы также предназначены для сбора элементов одного типа. Подумайте, какую коллекцию вы смогли бы представить в виде массива?
Объявление массива и получение доступа к его элементам
Следующий массив planets
содержит ровно восемь элементов:
1 |
var planets [8]string |
У каждого элемента массива одинаковый тип. В данном случае planets
является массивом строк.
К элементу массива можно получить доступ через использование квадратных скобок []
с нужным индексом, отсчет начинается с 0. Внизу представлен пример программы, а также проиллюстрирована схема.
1 2 3 4 5 6 7 8 |
var planets [8]string planets[0] = "Меркурий" // Присваивает планете индекс 0 planets[1] = "Венера" planets[2] = "Земля" earth := planets[2] // Получает планету с индексом 2 fmt.Println(earth) // Выводит: Земля |
Планеты с индексами от 0 до 7
Хотя только трем планетам были присвоены индексы, всего в массиве planets
находится восемь элементов. Длину массива можно определить через встроенную функцию len
. Другие элементы с нулевым значением своего типа, то есть пустая строка:
1 2 |
fmt.Println(len(planets)) // Выводит: 8 fmt.Println(planets[3] == "") // Выводит: true |
На заметку: В Go есть полезные встроенные функции, использовать которые можно без оператора
import
. Функцияlen
определяет длину типов. В данном случае возвращается размер массива.
Вопросы для проверки:
- Как можно получить доступ к первому элементу массива
planets
? - Каким будет значение элементов нового массива целых чисел по умолчанию?
Диапазон значений массива в Golang
У массива из восьми элементов индексы от 0 до 7. При попытке получить доступ к элементу за пределами диапазона массива компилятор Go сообщит об ошибке:
1 2 3 4 5 6 |
var planets [8]string // 8 - неверный номер индекса // находится за пределами диапазона массива из 8 элементов planets[8] = "Плутон" pluto := planets[8] |
Если компилятор Go не в состоянии зафиксировать ошибку, во время запуска программы может произойти сбой:
1 2 3 4 5 |
var planets [8]string i := 8 planets[i] = "Плутон" // Сбой: ошибка запуска pluto := planets[i] // индекс выходит за пределы диапазона |
Сбой приведет к аварийному завершению программы, что все-таки лучше, нежели модификация памяти, что не относится к массиву planets
. Будь это язык программирования вроде С, все могло бы закончиться неопределенным поведением.
Вопрос для проверки:
Приведет ли planets[11]
к ошибке во время компиляции или к сбою во время запуска?
Инициализация массивов через композитные литералы в Go
Композитный литерал является кратким синтаксисом для инициализации любого композитного типа с нужными значениями. Вместо объявления массива и присваивания каждого элемента по-очереди, композитный литеральный синтаксис Go объявит и инициализирует массив за один шаг, как показано в следующем примере:
1 |
dwarfs := [5]string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} |
Внутри фигурных скобок {}
находятся пять строк, что разделяются запятыми и являются элементами нового массива.
При работе с крупными массивами разделение композитного литерала на множество строк может сделать код более понятным. Компилятор Go может подсчитать количество элементов внутри композитного литерала, для этого вместо числа ставится многоточие (...
) . У массива planets
в следующем примере по-прежнему фиксированная длина:
1 2 3 4 5 6 7 8 9 10 |
planets := [...]string{ // Компилятор Go подсчитывает элементы "Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Уран", "Нептун", // Запятая в самом конце является обязательной } |
Задание для проверки:
Сколько планет указано в Листинге 3? Используйте встроенную функцию len
, чтобы выяснить.
Итерация через массивы в Go
Итерация через каждый элемент массива напоминает итерацию каждого символа строки. Мы ранее говорили об этом в уроке о строках в Golang. Это показано в примере ниже:
1 2 3 4 5 6 |
dwarfs := [5]string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} for i := 0; i < len(dwarfs); i++ { dwarf := dwarfs[i] fmt.Println(i, dwarf) } |
Ключевое слово range
возвращает индекс и значение каждого элемента массива посредством использования меньшего количества кода и меньшей вероятностью совершения ошибок, что показано в коде ниже:
1 2 3 4 5 |
dwarfs := [5]string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} for i, dwarf := range dwarfs { fmt.Println(i, dwarf) } |
Результат будет одинаковым для обеих программ:
1 2 3 4 5 |
0 Церера 1 Плутон 2 Хаумеа 3 Макемаке 4 Эрида |
На заметку: Помните, что вы можете использовать пустой идентификатор (подчеркивание), если вам не нужен индекс переменной, предоставленный range
.
Вопросы для проверки:
- Каких ошибок можно избежать, используя ключевое слово
range
для итерации через массив? - Когда вместо
range
лучше использовать цикл for?
Копирование массивов в Golang
Присваивание массива новой переменной или передача его функции приводит к копированию всего его содержимого, что показано в следующем примере:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
planets := [...]string{ "Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Уран", "Нептун", } planetsMarkII := planets // Копирует массив planets planets[2] = "упс" // Прокладывает путь для межзвездного шунтирования fmt.Println(planets) // Выводит: [Меркурий Венера упс Марс Юпитер Сатурн Уран Нептун] fmt.Println(planetsMarkII) // Выводит: [Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун] |
У массивов есть значения, функции также передают значения, а это значит, что функция terraform
в следующем листинге совершенно неэффективна:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package main import "fmt" // terraform ни к чему не приводит func terraform(planets [8]string) { for i := range planets { planets[i] = "New " + planets[i] } } func main() { planets := [...]string{ "Меркурий", "Венера", "Земля", "Марс", "Юпитер", "Сатурн", "Уран", "Нептун", } terraform(planets) fmt.Println(planets) // Выводит: [Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун] } |
Функция terraform
оперирует с копией массива planets
, поэтому модификации не затронут planets
в функции main
.
Также важно понимать, что длина массива является частью его типа. Типы [8]string
и [5]string
оба представляют собой наборы строк, но это совершенно разные типы. При попытке передать массив с другой длиной компилятор Go сообщит об ошибке:
1 2 |
dwarfs := [5]string{"Церера", "Плутон", "Хаумеа", "Макемаке", "Эрида"} terraform(dwarfs) // Нельзя использовать dwarfs (типа [5]string) как тип [8]string в качестве аргумента terraform |
Именно по этой причине массивы редко используются как параметры функции, в отличие от срезов массива, о которых мы поговорим в следующем уроке.
Задания для проверки:
- Как Земле удалось выжить в
planetsMarkII
из Листинга 6? - Как можно модифицировать Листинг 7, чтобы массив
planets
изmain
изменился?
Массивы из массивов в Golang
Пока что мы разобрали только массивы строк. В Go также можно создавать массивы целых чисел, чисел с плавающей запятой и даже массивы из массивов. Шахматная доска 8 х 8 представлена в следующем примере как массив из массива строк:
1 2 3 4 5 6 7 8 9 10 |
var board [8][8]string // Массив из восьми массивов с восемью строками board[0][0] = "r" board[0][7] = "r" // Ставит ладью на клетку с координатами [ряд][столбец] for column := range board[1] { board[1][column] = "p" } fmt.Print(board) |
Задание для проверки:
Подумайте об игре Судоку. Как можно объявить сетку целых чисел размером 9 х 9?
Заключение
- Массив является упорядоченным набором элементов с фиксированной длиной;
- Композитные литералы помогают легко инициализировать массивы;
- Ключевое слово
range
может итерировать через массивы; - При получении доступа к элементам массива нужно придерживаться границ диапазона;
- Во время присваивания и передачи функций массивы копируются.
Итоговое задание для проверки:
- Допишите Листинг 8 для отображения всех шахматных фигур на их стартовых позициях, используя символы kqrbnp для черных фигур в верхней части доски, а также символы в верхнем регистре KQRBNP для белых фигур в нижней части доски;
- Напишите функцию для отображения доски;
- Вместо строк, используйте
[8][8]rune
для доски. Помните, что литералы rune должны быть окружены одинарными кавычками и могут выводиться на экран через специальный символ%c
.
![](https://golangify.com/wp-content/uploads/2021/01/v.jpg)
Администрирую данный сайт с целью распространения как можно большего объема обучающего материала для языка программирования Go. В IT с 2008 года, с тех пор изучаю и применяю интересующие меня технологии. Проявляю огромный интерес к машинному обучению и анализу данных.
E-mail: vasile.buldumac@ati.utm.md
Образование
Технический Университет Молдовы (utm.md), Факультет Вычислительной Техники, Информатики и Микроэлектроники
- 2014 — 2018 Universitatea Tehnică a Moldovei, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Universitatea Tehnică a Moldovei, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»