Массивы и слайсы

16 вопросов

Слайсы - основная структура данных для работы с коллекциями в Go. Важно понимать их внутреннее устройство (указатель + длина + ёмкость) и отличие от массивов.

1 Какой результат: var s []int; fmt.Println(s == nil)? 🟢 Лёгкий
Ответ: A) true

Неинициализированный слайс имеет zero value nil. nil-слайс можно использовать с len() (вернёт 0), cap() (вернёт 0) и append() без ошибок. Но make([]int, 0) создаёт пустой не-nil слайс.

Подробнее →
2 Что вернёт cap(make([]int, 3, 10))? 🟢 Лёгкий
Ответ: B) 10

make([]int, length, capacity) - второй аргумент задаёт длину, третий - ёмкость. cap() возвращает ёмкость (10), len() - длину (3). Ёмкость определяет, сколько элементов можно добавить без переаллокации.

Подробнее →
3 Чем массив отличается от слайса? 🟢 Лёгкий
Ответ: B) Массив имеет фиксированный размер

Массив [3]int - фиксированный размер, часть типа. [3]int и [4]int - разные типы. Слайс []int - динамический, это ссылка на массив (указатель + длина + ёмкость). Массивы передаются по значению, слайсы - по ссылке.

Подробнее →
4 Как скопировать слайс? 🟢 Лёгкий
Ответ: B) copy(b, a)

Функция copy(dst, src) копирует элементы из src в dst, возвращая количество скопированных элементов. b = a - это не копирование, а создание второй ссылки на тот же массив.

Подробнее →
5 Что вернёт len(make([]int, 5, 10))? 🟢 Лёгкий
Ответ: B) 5

make([]int, 5, 10) создаёт слайс длиной 5 и ёмкостью 10. len() возвращает длину (количество доступных элементов), а не ёмкость. Элементы 0–4 инициализированы нулями.

Подробнее →
6 Что произойдёт: a := [3]int{1,2,3}; b := a; b[0] = 99; fmt.Println(a[0])? 🟡 Средний
Ответ: B) 1

Массивы в Go - value types. Присваивание b := a создаёт полную копию. Изменение b[0] не затрагивает a. Это ключевое отличие от слайсов, которые разделяют базовый массив.

Подробнее →
7 Что делает append(s, 1, 2, 3)? 🟡 Средний
Ответ: B) Возвращает новый слайс

append не изменяет оригинальный слайс - он возвращает новый. Если ёмкости хватает, новый слайс ссылается на тот же массив. Если нет - Go аллоцирует новый массив побольше. Всегда используйте: s = append(s, ...).

Подробнее →
8 Как удалить элемент из слайса по индексу i? 🟡 Средний
Ответ: C) append(s[:i], s[i+1:]...)

В Go нет встроенной функции удаления из слайса. Идиоматический способ - склеить части до и после удаляемого элемента через append. delete() работает только с map.

Подробнее →
9 Можно ли сравнивать слайсы оператором ==? 🟡 Средний
Ответ: B) Только с nil

Слайсы нельзя сравнивать между собой через == - это ошибка компиляции. Единственное допустимое сравнение - с nil. Для сравнения содержимого используйте slices.Equal() (Go 1.21+) или цикл.

Подробнее →
10 Что сделает clear(s) для слайса s := []int{1, 2, 3} (Go 1.21+)? 🟡 Средний
Ответ: B) Обнулит элементы, но len останется 3

Встроенная функция clear() для слайсов обнуляет все элементы zero value, но не меняет длину и ёмкость. После clear(s): s = [0, 0, 0], len(s) = 3. Для map clear удаляет все ключи.

Подробнее →
11 Что произойдёт при s := []int{1,2,3}; s2 := s[1:]; s2[0] = 99? 🔴 Сложный
Ответ: B) s[1] станет 99

Подслайс s[1:] разделяет базовый массив с s. s2[0] и s[1] указывают на один и тот же элемент в памяти. Изменение через s2 видно через s. Чтобы получить независимую копию, используйте copy.

Подробнее →
12 Что выведет: a := make([]int, 2, 4); b := append(a, 1); _ = append(a, 2); fmt.Println(b[2])? 🔴 Сложный
Ответ: B) 2

Оба append работают с одним базовым массивом (cap=4 хватает). Первый append записывает 1 в позицию [2]. Второй append тоже пишет в позицию [2], перезаписывая 1 на 2. b[2] теперь 2. Классическая ловушка разделяемой ёмкости.

Подробнее →
13 Что выведет: s := []int{1,2,3,4,5}; s2 := s[1:3:3]; s2 = append(s2, 99); fmt.Println(s[3])? 🔴 Сложный
Ответ: B) 4

Трёхиндексный слайс s[1:3:3] ограничивает ёмкость: len=2, cap=2. При append ёмкости не хватает - Go выделяет новый массив. s[3] остаётся 4. Без третьего индекса s[1:3] имел бы cap=4, и append перезаписал бы s[3].

Подробнее →
14 Есть ли утечка памяти: big := make([]byte, 1<<20); small := big[:10]; big = nil? 🔴 Сложный
Ответ: B) Да, small держит весь 1 МБ массив

small ссылается на тот же базовый массив размером 1 МБ. Пока small жив, GC не может его освободить. Решение: copy(newSlice, big[:10]). Частая проблема при чтении больших файлов, когда сохраняют маленький кусочек.

Подробнее →
15 Скомпилируется ли: s := []int{1, 2, 3}; a := [3]int(s) (Go 1.20+)? 🔴 Сложный
Ответ: B) Да, a будет копией данных слайса

Go 1.17 добавил конвертацию слайса в указатель на массив: (*[3]int)(s). Go 1.20 - прямую конвертацию: [3]int(s). Результат - копия данных, не ссылка. Если len(s) < 3 - panic. Полезно для функций, ожидающих массив фиксированного размера.

Подробнее →
16 По какой формуле растёт capacity слайса при append в Go 1.21+? 🔴 Сложный
Ответ: B) Удваивается до 256, затем рост ~25%

С Go 1.18: плавный рост - удвоение до 256 элементов, затем формула newcap += (newcap + 3*256) / 4. Это даёт плавный переход от 2x к ~1.25x. Точный cap может отличаться из-за выравнивания памяти аллокатором. Раньше: удвоение до 1024, затем +25%.

Подробнее →
🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.