- Объявление массива
- Инициализация значениями
- Доступ к элементам и их изменение
- Длина массива
- Передача и возврат из функции
- Пример: Переворот строки
- Применение массивов на практике
Массив — это структура данных, содержащая фиксированное количество элементов одного типа. Это поведение похоже на массивы в языках вроде C или Pascal, где размер известен во время компиляции и не может изменяться после создания.
Объявление массива
Тип массива составной, он включает в себя информацию о том, что это массив и о том, какой тип хранится внутри него.
var nums [5]int
- Тип: массив из пяти
int
. - Все значения инициализируются нулями (
0
дляint
).
Можно использовать короткую форму:
// Скобки обязательны
nums := [5]int{}
Скобки {}
здесь обязательны, потому что они указывают на создание литерала массива. Даже если значения по умолчанию, Go требует явного указания структуры.
Если указать меньше значений, оставшиеся элементы будут инициализированы нулями.
nums := [4]int{1, 2}
Во всех остальных случаях несовпадения, произойдет ошибка компиляции. Go строго проверяет соответствие длины и количества элементов.
Инициализация значениями
Для добавления конкретных значений, достаточно их перечислить через запятую в фигурных скобках.
nums := [3]int{1, 2, 3}
Если указано больше элементов, чем заданная длина — будет ошибка компиляции.
nums := [1]int{1, 2} // ошибка: index 1 out of bounds [0:1]
Можно также задать длину неявно, используя ...
. Она посчитается автоматически, на основе переданных значений во время инициализации:
nums := [...]int{10, 20, 30} // длина будет равна 3
Доступ к элементам и их изменение
Синтаксически доступ к массивам такой же как и в большинстве других языков. Индексация тоже начинается с нуля.
nums := [3]int{1, 2, 3}
fmt.Println(nums[1]) // => 2
nums[2] = 33
fmt.Println(nums) // => [1 2 33]
Обращение за пределы массива вызывает ошибку компиляции:
words := [2]string{}
words[2] // ошибка: index 2 out of bounds [0:2]
Длина массива
Go предоставляет встроенную функцию len()
для получения длины массива. Эта длина известна во время компиляции и не меняется.
fmt.Println(len([5]int{1, 2, 3})) // => 5
fmt.Println(len([10]int{})) // => 10
Передача и возврат из функции
Массивы передаются и возвращаются по значению, то есть копируются. Даже если изменить массив внутри функции, оригинал не изменится.
func modify(items [3]int) [3]int {
items[0] = 100
return items
}
func main() {
a := [3]int{1, 2, 3}
b := modify(a)
// оригинал не изменился
fmt.Println(a) // => [1 2 3]
// результат функции
fmt.Println(b) // [100 2 3]
}
Чтобы изменить массив "на месте", обычно передают указатель на массив (*[3]int
) или используют срез.
Пример: Переворот строки
Посмотрим на комплексный пример использования массива вместе с циклом. Ниже происходит переворот строки, заранее разбитой на массив рун.
func reverse(text [5]rune) [5]rune {
var result [5]rune
for i := 0; i < len(text); i++ {
result[i] = text[len(text) - 1 - i]
}
return result
}
func main() {
text := [5]rune{'п', 'р', 'и', 'в', 'е'}
reversed := reverse(text)
fmt.Println(string(reversed[:])) // => "евирп"
}
Применение массивов на практике
Фиксированная длина делает массивы неудобными для большинства задач, где размер данных заранее неизвестен. Например, если вы читаете данные из файла, получаете значения из сети или формируете список на основе пользовательского ввода — вы не можете заранее указать точное количество элементов. А так как длина массива в Go жёстко зашита в его тип, менять её динамически невозможно. Поэтому на практике почти всегда используют срезы (slices
) — они позволяют работать с коллекциями переменной длины.