← Назад к вопросам

Какие особенности есть у массива?

1.3 Junior🔥 161 комментариев
#Основы Go#Производительность и оптимизация

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Особенности массивов в Go

Массивы в Go — это одна из фундаментальных структур данных, имеющие уникальные характеристики, отличающие их от многих других языков программирования.

Основные особенности массивов

1. Фиксированная длина Массив в Go имеет неизменяемую длину, определяемую при создании. Это кардинальное отличие от срезов (slices).

// Массив из 5 целых чисел
var arr [5]int

// Инициализация с явной длиной
numbers := [5]int{1, 2, 3, 4, 5}

// Неявная длина (компилятор вычисляет)
values := [...]int{10, 20, 30}  // длина = 3

// Попытка добавить элемент вызовет ошибку компиляции
// arr[5] = 100  // ошибка: index out of range

2. Массив — это значение, не указатель Массивы в Go — это значимые типы. Это означает, что при присвоении или передаче функции копируется весь массив.

func modifyArray(arr [3]int) {
    arr[0] = 999
}

func main() {
    original := [3]int{1, 2, 3}
    modifyArray(original)
    fmt.Println(original)  // [1 2 3] - не изменилось!
    
    // Для изменения нужен указатель
    modifyArrayPointer(&original)
    fmt.Println(original)  // [999 2 3] - изменилось!
}

func modifyArrayPointer(arr *[3]int) {
    arr[0] = 999
}

3. Тип массива включает длину Два массива с одинаковыми элементами, но разными длинами — это разные типы.

var a [5]int
var b [10]int
// a и b — разные типы!
// b = a  // ошибка компиляции

var c [5]int
c = a  // OK - оба типа [5]int

4. Использование указателей для эффективности Поскольку массивы копируются при передаче, для больших массивов рекомендуется использовать указатели или срезы.

func processLargeArray(arr *[1000000]int) {
    arr[0] = 42  // изменение оригинального массива
}

func main() {
    huge := [1000000]int{}
    processLargeArray(&huge)  // передача указателя
}

5. Сравнение массивов Массивы можно сравнивать напрямую (в отличие от срезов).

a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
fmt.Println(a == b)  // true

c := [3]int{1, 2, 4}
fmt.Println(a == c)  // false

// Срезы нельзя сравнивать
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
// slice1 == slice2  // ошибка компиляции

6. Итерация и range Массивы полностью совместимы с оператором range.

arr := [3]string{"a", "b", "c"}
for i, v := range arr {
    fmt.Printf("Index: %d, Value: %s\n", i, v)
}

Массивы vs Срезы

Хотя массивы имеют фиксированную длину, Go обычно рекомендует использовать срезы для большинства случаев, так как они более гибкие и динамичные. Массивы в основном используются как:

  • Основа для срезов
  • Когда точно известна фиксированная длина
  • В производительно-критичном коде

Заключение

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