---
title: Массивы и слайсы
seo:
  title: Массивы и слайсы — Go Developer
  description: Тема «Массивы и слайсы» для собеседования Go Developer. Что такое слайс (slice) и массив (array)? Чем отличается массив от слайса? Как устроен слайс в Go?
---

[Все темы Go Developer](/go-developer)

## <strong>Что такое слайс (</strong><code>slice</code><strong>) и массив (</strong><code>array</code><strong>)? Чем отличается массив от слайса?</strong> [#q-14bee738d69b812695e4db6ec6e38a8c]

Массивы и слайсы имеют свои преимущества и недостатки.

#### Массив (Array) в Go&#58;

- <strong>Определение</strong>&#58; Статически типизированная структура данных с
  фиксированным размером.

- <strong>Объявление</strong>&#58; Размер массива указывается при его создании.

- <strong>Пример</strong>&#58;

  ```go
  var arr [5]int
  arr = [5]int{1, 2, 3, 4, 5}
  ```

#### Слайс (Slice) в Go&#58;

- Определение&#58; Статически типизированный срез базового массива. Длина слайса может меняться, а тип его элементов задается при компиляции.

- <strong>Объявление</strong>&#58; Размер слайса не фиксирован и может
  изменяться.

- <strong>Пример</strong>&#58;

  ```go
  var slice []int
  slice = []int{1, 2, 3, 4, 5}
  ```

#### Основные отличия&#58;

{/* prettier-ignore */}
1. <strong>Размер</strong>&#58;

    - <strong>Массив</strong>&#58; Фиксированный размер, определяемый при создании.

    - <strong>Слайс</strong>&#58; Динамический размер, может изменяться в ходе выполнения программы.

1. <strong>Гибкость</strong>&#58;

    - <strong>Массив</strong>&#58; Менее гибкий из-за фиксированного размера.

    - <strong>Слайс</strong>&#58; Более гибкий, поддерживает добавление и удаление элементов.

1. <strong>Создание</strong>&#58;

    - <strong>Массив</strong>&#58; <code>var arr &#91;5&#93;int</code>

    - <strong>Слайс</strong>&#58; <code>var slice &#91;&#93;int</code> или с помощью функции <code>make</code>&#58; <code>slice &#58;&#61; make&#40;&#91;&#93;int&#44; 5&#41;</code>

1. <strong>Использование и расширение</strong>&#58;

    - <strong>Массив</strong>&#58; Не может быть изменен в размере после создания.

    - <strong>Слайс</strong>&#58; Можно изменять с помощью встроенных функций, таких как <code>append</code>.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как устроен слайс в Go?</strong> [#q-14bee738d69b817fa885cfc262e18eea]

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

#### Основные характеристики&#58;

{/* prettier-ignore */}
1. <strong>Гибкость размера</strong>&#58;

    - Размер слайса может изменяться в ходе выполнения программы.

    - Пример&#58; <code>slice &#58;&#61; &#91;&#93;int&#123;1&#44; 2&#44; 3&#125;</code> создает слайс из 3 элементов, к которому можно добавить новые элементы.

1. <strong>Поддержка операций добавления и удаления</strong>&#58;

    - Можно добавлять элементы с помощью функции <code>append</code>.

    - Пример&#58; <code>slice &#61; append&#40;slice&#44; 4&#41;</code> добавляет элемент в слайс.

1. <strong>Индексация и длина</strong>&#58;

    - Доступ к элементам осуществляется по индексу, как в массиве.

    - Длина слайса определяется функцией <code>len&#40;slice&#41;</code>.

    - Пример&#58; <code>fmt&#46;Println&#40;slice&#91;0&#93;&#41;</code> и <code>fmt&#46;Println&#40;len&#40;slice&#41;&#41;</code>.

1. <strong>Подкапотное устройство</strong>&#58;

    - Слайс содержит указатель на массив, длину (len) и вместимость (cap).

    - Вместимость (capacity) определяет количество элементов, которые слайс может содержать без выделения новой памяти.

#### Пример кода&#58;

```go
package main

import "fmt"

func main() {
    // Создание слайса с начальной длиной и емкостью
    slice := []int{1, 2, 3}

    // Добавление элементов в слайс
    slice = append(slice, 4, 5)

    // Доступ к элементам слайса
    fmt.Println(slice[0]) // Вывод: 1

    // Длина и емкость слайса
    fmt.Println("Length:", len(slice)) // Вывод: Length: 5
    fmt.Println("Capacity:", cap(slice)) // Вывод: Capacity: 6 (емкость может варьироваться)
}
```

Слайсы в Go обеспечивают удобную работу с динамическими коллекциями данных, предоставляя гибкость и простоту использования.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как устроен массив в Go?</strong> [#q-14bee738d69b81da8581e09a0407713e]

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

#### Основные характеристики&#58;

{/* prettier-ignore */}
1. <strong>Фиксированный размер</strong>&#58;

    - Размер массива определяется при его создании и не может быть изменен.

    - Пример&#58; <code>var arr &#91;5&#93;int</code> создает массив из 5 целых чисел.

1. <strong>Статическая типизация</strong>&#58;

    - Тип элементов массива задается при объявлении.

    - Пример&#58; <code>var arr &#91;3&#93;string</code> создает массив из 3 строк.

1. <strong>Индексация</strong>&#58;

    - Доступ к элементам массива осуществляется по индексу, начиная с 0.

    - Пример&#58; <code>arr&#91;0&#93;</code> доступ к первому элементу массива.

1. <strong>Инициализация</strong>&#58;

    - Массив можно инициализировать при создании.

    - Пример&#58; <code>arr &#58;&#61; &#91;3&#93;int&#123;1&#44; 2&#44; 3&#125;</code>

#### Пример кода&#58;

```go
package main

import "fmt"

func main() {
    // Объявление и инициализация массива
    var arr [5]int = [5]int{1, 2, 3, 4, 5}

    // Доступ к элементам массива
    fmt.Println(arr[0]) // Вывод: 1

    // Изменение элемента массива
    arr[2] = 10
    fmt.Println(arr) // Вывод: [1 2 10 4 5]
}
```

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

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как можно создать слайс?</strong> [#q-14bee738d69b8157bcfae5a41e21952c]

В Go слайс можно создать несколькими способами&#58;

1. <strong>Создание слайса с помощью литерала</strong>&#58;

   ```go
   slice := []int{1, 2, 3}
   ```

1. <strong>Создание пустого слайса и его инициализация</strong>&#58;

   ```go
   var slice []int
   slice = append(slice, 1, 2, 3)
   ```

1. <strong>Использование функции</strong> <code>make</code>&#58;

   ```go
   slice := make([]int, 5)       // Создание слайса с длиной 5 и нулевыми значениями
   sliceWithCapacity := make([]int, 5, 10) // Слайс длиной 5 и емкостью 10
   ```

1. <strong>Создание слайса из массива</strong>&#58;

   ```go
   array := [5]int{1, 2, 3, 4, 5}
   slice := array[1:4]           // Слайс включает элементы с 1-го по 3-й индексы (2, 3, 4)
   ```

#### Примеры&#58;

1. <strong>Слайс с литералом</strong>&#58;

   ```go
   slice := []string{"apple", "banana", "cherry"}
   ```

1. <strong>Пустой слайс с инициализацией</strong>&#58;

   ```go
   var slice []int
   slice = append(slice, 10, 20, 30)
   ```

1. <strong>Слайс с</strong> <code>make</code>&#58;

   ```go
   slice := make([]int, 5)       // Создание слайса длиной 5
   sliceWithCapacity := make([]int, 5, 10) // Создание слайса длиной 5 и емкостью 10
   ```

1. <strong>Слайс из массива</strong>&#58;

   ```go
   array := [5]int{1, 2, 3, 4, 5}
   slice := array[1:4]           // Слайс содержит [2 3 4]
   ```

Эти способы позволяют создавать слайсы для различных нужд, обеспечивая гибкость и удобство работы с данными в Go.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Что такое</strong> <code>zero&#45;value</code> <strong>и какое оно у слайса?</strong> [#q-14bee738d69b816dbc9ddec5b92d604c]

<code>Zero&#45;value</code> — это значение по умолчанию, которое присваивается
переменной, когда она объявлена, но не инициализирована явно. Для каждого типа в
Go существует свое zero-value.

#### Zero-value для слайса&#58;

Для слайсов zero-value — это <code>nil</code> и длина равная 0.

#### Пример&#58;

```go
var slice []int // zero-value для слайса
fmt.Println(slice == nil) // true
fmt.Println(len(slice))   // 0
```

В этом примере <code>slice</code> имеет zero-value, что означает, что он <code>nil</code> и его длина равна 0. Слайс с zero-value можно использовать, например, в функциях <code>append</code>, и он будет работать корректно.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Что такое</strong> <code>nil slice</code> <strong>и чем отличается? Можно ли добавлять элементы в</strong> <code>nil slice</code><strong>?</strong> [#q-14bee738d69b815b96abd3651d4dc88c]

<code>nil slice</code> — это слайс, который не указывает на какой-либо массив,
его zero-value. <code>nil slice</code> имеет длину и емкость равные нулю.

#### Отличия <code>nil slice</code>&#58;

{/* prettier-ignore */}
1. <strong>Инициализация</strong>&#58;

    - Nil слайс&#58; не инициализирован и равен <code>nil</code>.

    - Пустой слайс&#58; инициализирован, но не содержит элементов, например, созданный с помощью <code>make&#40;&#91;&#93;int&#44; 0&#41;</code>.

1. <strong>Проверка на nil</strong>&#58;

    - Можно проверить, является ли слайс nil с помощью сравнения с <code>nil</code>.

#### Пример&#58;

```go
var nilSlice []int // nil слайс
emptySlice := make([]int, 0) // пустой слайс

fmt.Println(nilSlice == nil) // true
fmt.Println(emptySlice == nil) // false
```

#### Добавление элементов в <code>nil slice</code>&#58;

Да, можно добавлять элементы в nil slice с помощью функции <code>append</code>. При этом Go автоматически выделит память для слайса.

#### Пример добавления в <code>nil slice</code>&#58;

```go
var nilSlice []int
nilSlice = append(nilSlice, 1, 2, 3)
fmt.Println(nilSlice) // [1 2 3]
```

В этом примере элементы успешно добавляются в nil слайс, и Go корректно обрабатывает выделение памяти.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как проверить слайс на пустоту?</strong> [#q-14bee738d69b816f815fe651c97ee9ea]

Пример проверки слайса на пустоту&#58;

```go
var slice []int

if len(slice) == 0 {
    fmt.Println("Slice is empty")
} else {
    fmt.Println("Slice is not empty")
}
```

В этом примере, если длина слайса <code>slice</code> равна нулю, выводится сообщение "Slice is empty".

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как работает базовая функция append для слайсов? Можно ли применить к массивам? Напишите свою функцию append</strong> [#q-14bee738d69b816888e2de185dfa211c]

Функция <code>append</code> в Go добавляет элементы к слайсу, расширяя его при необходимости. Если текущая емкость слайса недостаточна, создается новый массив большего размера, копируются существующие элементы и добавляются новые.

#### Пример использования <code>append</code>&#58;

```go
slice := []int{1, 2, 3}
slice = append(slice, 4, 5)
fmt.Println(slice) // Вывод: [1 2 3 4 5]
```

#### Применение к массивам&#58;

Функцию <code>append</code> нельзя применить непосредственно к массивам, так как она предназначена только для слайсов. Но можно создать слайс на основе массива и затем использовать <code>append</code>.

#### Пример функции <code>append</code>&#58;

```go
package main

import "fmt"

func myAppend(slice []int, elements ...int) []int {
    oldLen := len(slice)
    newLen := oldLen + len(elements)
    if newLen > cap(slice) {
        grown := make([]int, newLen)
        copy(grown, slice)
        slice = grown
    } else {
        slice = slice[:newLen]
    }
    copy(slice[oldLen:], elements)
    return slice
}

func main() {
    slice := []int{1, 2, 3}
    slice = myAppend(slice, 4, 5)
    fmt.Println(slice) // Вывод: [1 2 3 4 5]
}
```

В этом примере функция <code>myAppend</code> добавляет элементы к слайсу и возвращает обновленный слайс.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как можно добавить элементы в слайс? Что будет если элемент не вмещается в размер слайса?</strong> [#q-14bee738d69b819f8e4ae2d9e20f8456]

В Go для добавления элементов в слайс используется функция <code>append</code>.

#### Пример добавления элементов&#58;

```go
slice := []int{1, 2, 3}
slice = append(slice, 4, 5)
fmt.Println(slice) // Вывод: [1 2 3 4 5]
```

#### Что происходит, если элемент не вмещается в размер слайса&#58;

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

#### Пример с недостаточной емкостью&#58;

```go
slice := make([]int, 3, 3) // Создание слайса длиной 3 и емкостью 3
slice[0], slice[1], slice[2] = 1, 2, 3

slice = append(slice, 4) // Добавление нового элемента, перераспределение памяти
fmt.Println(slice) // Вывод: [1 2 3 4]
```

В этом примере начальная емкость слайса равна 3. При добавлении четвертого элемента Go перераспределяет память и увеличивает емкость слайса.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как можно слить два слайса?</strong> [#q-14bee738d69b81a1941de8469737ef31]

В Go можно слить два слайса с помощью функции <code>append</code>. Просто передайте второй слайс как аргументы к <code>append</code> с помощью <code>&#46;&#46;&#46;</code>.

#### Пример слияния двух слайсов&#58;

```go
slice1 := []int{1, 2, 3}
slice2 := []int{4, 5, 6}

mergedSlice := append(slice1, slice2...)
fmt.Println(mergedSlice) // Вывод: [1 2 3 4 5 6]
```

#### Объяснение&#58;

- <code>slice2&#46;&#46;&#46;</code> распаковывает элементы второго слайса,
  позволяя <code>append</code> добавить их к первому слайсу.

- Результат append нужно сохранить&#58; он возвращает слайс с новой длиной. Если емкости достаточно, результат использует прежний базовый массив и может изменить данные других слайсов на тот же массив.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## Как получить срез слайса и избежать ошибок с общим массивом? [#q-14bee738d69b814a8ca3d2590beb1992]

Для нарезки слайса используется синтаксис <code>slice&#91;start&#58;end&#93;</code>, где <code>start</code> — начальный индекс (включительно), а <code>end</code> — конечный индекс (исключительно).

#### Примеры нарезки&#58;

```go
slice := []int{1, 2, 3, 4, 5}

subslice1 := slice[1:3]  // содержит элементы с индексами 1 и 2: [2 3]
subslice2 := slice[:2]   // содержит первые два элемента: [1 2]
subslice3 := slice[2:]   // содержит элементы с индекса 2 до конца: [3 4 5]
```

#### Нюансы и подводные камни&#58;

1. <strong>Общие данные</strong>&#58; Нарезка слайса создает новый слайс,
   который ссылается на тот же базовый массив. Изменения в одном слайсе могут
   повлиять на другой.

   ```go
   slice := []int{1, 2, 3, 4, 5}
   subslice := slice[1:3]
   subslice[0] = 10
   fmt.Println(slice)     // Вывод: [1 10 3 4 5]
   ```

1. Ограничения по индексам&#58; для слайса s выражение s\[low&#58;high\] требует 0 ≤ low ≤ high ≤ cap(s). Верхняя граница может превышать len(s); нарушение границ вызывает панику.

   ```go
   slice := []int{1, 2, 3, 4, 5}
   // subslice := slice[1:6] // panic: runtime error: slice bounds out of range
   ```

1. <strong>Изменение длины и емкости</strong>&#58; Нарезанный слайс имеет свою
   длину и емкость, которая может быть меньше или равна емкости исходного
   слайса.

   ```go
   slice := []int{1, 2, 3, 4, 5}
   subslice := slice[1:3]
   fmt.Println(len(subslice))  // Вывод: 2
   fmt.Println(cap(subslice))  // Вывод: 4: cap(slice) - 1
   ```

Нарезка слайсов в Go удобна, но требует внимательного отношения к изменениям базового массива и индексам.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::

---

## <strong>Как можно скопировать слайс? Что такое функция copy? Как добиться аналогичного поведения copy с помощью append?</strong> [#q-14bee738d69b81928e6fc7b57a26bad2]

Для копирования слайсов можно использовать встроенную функцию <code>copy</code>.

Функция <code>copy</code> копирует элементы из одного слайса в другой. Возвращает количество скопированных элементов.

```go
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
fmt.Println(dst) // Вывод: [1 2 3]
```

Для достижения аналогичного поведения функции <code>copy</code> можно использовать <code>append</code>&#58;

```go
src := []int{1, 2, 3}
dst := append([]int(nil), src...)
fmt.Println(dst) // Вывод: [1 2 3]
```

В этом примере создается новый слайс <code>&#91;&#93;int&#40;nil&#41;</code>, к которому добавляются все элементы из <code>src</code> с помощью <code>append</code>.

:::note[Ссылки для изучения]

1. [Массивы и слайсы в Golang](https://habr.com/ru/articles/739754/)
   :::
