Упражнение. Использование массивов

Завершено

Массив в Go — это структура данных определенного типа с фиксированной длиной. Массив содержит несколько элементов (а также может не содержать ни одного элемента). Размер массива необходимо определить при объявлении или инициализации массива. Изменить размер массива после создания массива невозможно. По этим причинам массивы обычно не используются в программах Go, но они выступают в качестве основы для срезов и карт.

Объявление массивов

Чтобы объявить массив в Go, необходимо определить тип данных его элементов и число элементов, которые могут храниться в массиве. Затем можно получить доступ к каждому элементу массива с помощью индекса. Первый элемент имеет нулевой индекс, а индекс последнего элемента на единицу меньше длины массива (длина — 1).

Рассмотрим следующий код:

package main

import "fmt"

func main() {
    var a [3]int
    a[1] = 10
    fmt.Println(a[0])
    fmt.Println(a[1])
    fmt.Println(a[len(a)-1])
}

При выполнении приведенного выше кода получается следующий результат:

0
10
0

Несмотря на то, что массив был объявлен, при доступе к его элементам не возникает ошибок. По умолчанию Go инициализирует каждый элемент с типом данных по умолчанию. В данном случае значение по умолчанию для типа int равно нулю. Но вы можете назначить значение определенной позиции, как мы сделали с a[1] = 10. Доступ к этому элементу можно получить с помощью такого же синтаксиса. Кроме того, обратите внимание, что для ссылки на первый элемент мы использовали a[0]. Для ссылки на последний элемент мы использовали a[len(a)-1]. Функция len — это встроенная функция Go, используемая для получения числа элементов в массиве, срезе или карте.

Инициализация массивов

При объявлении массива его также можно инициализировать с другими значениями, отличными от значений по умолчанию. Ознакомиться с этим синтаксисом и протестировать его можно с помощью следующего фрагмента кода:

package main

import "fmt"

func main() {
    cities := [5]string{"New York", "Paris", "Berlin", "Madrid"}
    fmt.Println("Cities:", cities)
}

При выполнении приведенного выше кода получается следующий результат:

Cities: [New York Paris Berlin Madrid ]

Хотя массив содержит пять элементов, присваивать значения всем элементам необязательно. Как мы видели раньше, последняя позиция имеет пустую строку, так как это значение по умолчанию для строкового типа данных.

Многоточие в массивах

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

q := [...]int{1, 2, 3}

Давайте изменим программу, которая использовалась в предыдущем разделе, применяя многоточие. Код должен выглядеть так:

package main

import "fmt"

func main() {
    cities := [...]string{"New York", "Paris", "Berlin", "Madrid"}
    fmt.Println("Cities:", cities)
}

При выполнении приведенного выше кода вы получите результат, похожий на предыдущий:

Cities: [New York Paris Berlin Madrid]

Видите ли вы разницу? В конце массива отсутствует пустая строка. Длина массива была определена теми строками, которые были указаны при инициализации. В этом случае вы не резервируете ту память, которая может и не понадобиться.

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

package main

import "fmt"

func main() {
    numbers := [...]int{99: -1}
    fmt.Println("First Position:", numbers[0])
    fmt.Println("Last Position:", numbers[99])
    fmt.Println("Length:", len(numbers))
}

Выполните этот код, и вы получите следующий результат:

First Position: 0
Last Position: -1
Length: 100

Обратите внимание, что длина массива равна 100, так как вы указали значение для 99-го элемента. Первая позиция выводит значение по умолчанию (ноль).

Многомерные массивы

Go поддерживает многомерные массивы для работы со сложными структурами данных. Давайте создадим программу, в которой объявляется и инициализируется двумерный массив. Используйте следующий код:

package main

import "fmt"

func main() {
    var twoD [3][5]int
    for i := 0; i < 3; i++ {
        for j := 0; j < 5; j++ {
            twoD[i][j] = (i + 1) * (j + 1)
        }
        fmt.Println("Row", i, twoD[i])
    }
    fmt.Println("\nAll at once:", twoD)
}

При выполнении приведенной выше программы вы получите следующий результат:

Row 0 [1 2 3 4 5]
Row 1 [2 4 6 8 10]
Row 2 [3 6 9 12 15]

All at once: [[1 2 3 4 5] [2 4 6 8 10] [3 6 9 12 15]]

Вы объявили двумерный массив, указав, сколько элементов будет находиться во втором измерении, следующим образом: var twoD [3][5]int. Этот массив можно рассматривать как структуру данных со столбцами и строками, как матрицу или электронную таблицу. Изначально все элементы массива имеют значение по умолчанию (ноль). В цикле for мы инициализируем элементы массива с различными значениями в каждой строке. Наконец, вы печатаете все его значения в терминале.

А как объявить трехмерный массив? Ведь синтаксис должен быть таким же, верно? Это можно сделать так, как показано в следующем примере:

package main

import "fmt"

func main() {
    var threeD [3][5][2]int
    for i := 0; i < 3; i++ {
        for j := 0; j < 5; j++ {
            for k := 0; k < 2; k++ {
                threeD[i][j][k] = (i + 1) * (j + 1) * (k + 1)
            }
        }
    }
    fmt.Println("\nAll at once:", threeD)
}

При выполнении приведенного выше кода получается следующий результат:

All at once: [[[1 2] [2 4] [3 6] [4 8] [5 10]] [[2 4] [4 8] [6 12] [8 16] [10 20]] [[3 6] [6 12] [9 18] [12 24] [15 30]]]

Если отформатировать выходные данные в более удобном формате, мы получим следующий результат:

All at once: 
[
    [
        [1 2] [2 4] [3 6] [4 8] [5 10]
    ] 
    [
        [2 4] [4 8] [6 12] [8 16] [10 20]
    ] 
    [
        [3 6] [6 12] [9 18] [12 24] [15 30]
    ]
]

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