> Происходит ли копирование данных при передаче слайса и массива в функцию в Go (Go)
Уровень: middle · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Avito
Стек: Go
> Пример ответа
Короткий ответ
При передаче массива в функцию происходит полное копирование всех элементов - массив передаётся по значению. При передаче слайса копируется только его заголовок (структура slice header: указатель на массив, длина и ёмкость), а сами данные не копируются. Слайс - это ссылочный тип, но передаётся он по значению, то есть копируется именно заголовок, а не содержимое.
Подробное объяснение
В Go массивы - это значения фиксированной длины. Когда вы передаёте массив в функцию, компилятор создаёт полную копию всех элементов в стеке или куче. Это означает, что изменения, сделанные внутри функции, не повлияют на исходный массив.
Слайс - это дескриптор, состоящий из трёх полей:
- указатель на первый элемент массива (или на начало сегмента)
- длина (len)
- ёмкость (cap)
При передаче слайса в функцию копируется только этот заголовок (24 байта на 64-битной платформе). Сами данные остаются в исходном массиве, и обе стороны работают с одним и тем же underlying array.
Важный нюанс: если внутри функции вы изменяете элементы слайса через индексацию, изменения будут видны в вызывающем коде, потому что оба заголовка указывают на один и тот же массив. Но если вы меняете сам заголовок (например, через append, который вызывает перераспределение), то внешний слайс не изменится.
На практике
На практике это означает:
- Передача больших массивов в функцию - дорогая операция, так как копируется всё содержимое. Для больших данных лучше использовать указатели на массив или слайсы.
- Слайсы - стандартный способ работы с последовательностями данных в Go, именно из-за дешёвой передачи заголовка.
- Если нужно гарантировать, что функция не изменит данные, передавайте массив по значению или копируйте слайс внутри функции.
- При работе с append внутри функции будьте осторожны: если ёмкости достаточно, изменения затронут исходный массив; если нет - будет создан новый массив, и внешний слайс останется без изменений.
Пример кода
GOpackage mainimport "fmt"func modifyArray(arr [3]int) {arr[0] = 100 // не повлияет на исходный массив}func modifySlice(s []int) {s[0] = 200 // повлияет на исходный массив, так как данные общие}func appendToSlice(s []int) {s = append(s, 300) // не повлияет на внешний слайс, если произошло перераспределение// но если ёмкости хватало, то внешний слайс тоже увидит новый элемент (если длина позволяет)}func main() {arr := [3]int{1, 2, 3}modifyArray(arr)fmt.Println(arr) // [1 2 3]slice := []int{1, 2, 3}modifySlice(slice)fmt.Println(slice) // [200 2 3]slice2 := []int{1, 2, 3}appendToSlice(slice2)fmt.Println(slice2) // [200 2 3] - длина не изменилась}
Как отвечать на собеседовании
Начните с чёткого разграничения: массив - значение, слайс - ссылка на данные. Подчеркните, что слайс передаётся по значению, но это значение содержит указатель на массив. Обязательно упомяните, что изменения элементов через слайс видны вызывающему коду, а изменения заголовка (len, cap, перераспределение) - нет. Хорошо добавить пример с append и объяснить, когда происходит перераспределение.
Что проверяет интервьюер
Интервьюер проверяет:
- понимание разницы между массивом и слайсом
- знание внутреннего устройства слайса (slice header)
- понимание семантики передачи по значению в Go
- умение предсказывать поведение кода с append и изменением элементов
- осознание последствий для производительности (копирование больших массивов)
Типичные ошибки
- Утверждение, что слайс передаётся по ссылке - это неверно, передаётся копия заголовка
- Ожидание, что append внутри функции изменит внешний слайс - это верно только при достаточной ёмкости
- Игнорирование того, что изменение элементов слайса внутри функции влияет на исходные данные
- Путаница между копированием заголовка и копированием данных
- Забывание, что массив можно передать по указателю, если нужно избежать копирования
> Похожие задачи по Go
Как описать схему базы данных для модели библиотеки с сущностями автор, книга, читатель и связями между ними
Какие сигналы существуют в операционной системе
Расскажите про опыт оптимизации
Напиши SQL запрос для вывода суммы продаж по каждому пользователю, учитывая, что у пользователя может не быть продаж
> Похожие задачи по backend
Как описать схему базы данных для модели библиотеки с сущностями автор, книга, читатель и связями между ними
Какие сигналы существуют в операционной системе
Какие типы данных относятся к мутабельным, а какие к немутируемым
Можно ли объявить поле так, чтобы оно было примитивом после компиляции
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью