> Когда происходит копирование элементов при передаче массива или слайса в функцию в Go (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Wildberries, Avito

Стек: Go

> Пример ответа

Короткий ответ

В Go при передаче массива в функцию происходит полное копирование всех элементов - массив передаётся по значению. Слайс передаётся как структура из трёх полей (указатель на массив, длина, ёмкость), при этом сами элементы не копируются - копируется только заголовок слайса. Изменение элементов через слайс внутри функции затронет исходный массив, а изменение длины или ёмкости - нет.

Подробное объяснение

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

Слайс - это дескриптор, который содержит:

  • указатель на первый элемент массива (или nil)
  • длину (len)
  • ёмкость (cap)

При передаче слайса в функцию копируется только этот дескриптор (24 байта на 64-битной платформе). Указатель внутри копии ссылается на тот же самый массив, поэтому изменения элементов через индексацию или срезы будут видны вызывающему коду.

Важный нюанс: если внутри функции вы делаете append и это приводит к превышению ёмкости, создаётся новый массив, и указатель в локальной копии слайса начинает ссылаться на него. Исходный слайс при этом остаётся неизменным.

На практике

Для senior-позиции важно понимать, когда копирование действительно происходит:

  1. Передача массива по значению - всегда копия, даже если массив огромный. Для больших массивов это может быть дорого.
  2. Передача слайса - копируется только заголовок, но не данные. Это дёшево и обычно предпочтительно.
  3. Если нужно гарантированно изменить массив в функции - передавайте указатель на массив *[N]T.
  4. Если нужно изменить длину слайса внутри функции и сохранить это изменение - возвращайте новый слайс или передавайте указатель на слайс *[]T.

На практике в Go почти всегда используют слайсы, а не массивы, именно из-за дешёвой передачи и гибкости.

Пример кода

GO
package main
import "fmt"
func modifyArray(arr [3]int) {
arr[0] = 100 // изменение не повлияет на оригинал
}
func modifySlice(s []int) {
s[0] = 200 // изменение повлияет на оригинал
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] - длина не изменилась, но элемент изменён
}

Как отвечать на собеседовании

Начните с чёткого разграничения: массив - значение, слайс - ссылочная структура. Затем объясните механику: копирование массива целиком, копирование заголовка слайса. Обязательно упомяните поведение append при превышении ёмкости - это ключевой момент для senior. Приведите пример, показывающий разницу. Если спросят про производительность - скажите, что передача слайса O(1) по времени и памяти, а массива - O(n). Можно добавить, что в реальном коде массивы редко передают напрямую, обычно используют слайсы или указатели.

Что проверяет интервьюер

Интервьюер проверяет:

  • понимание модели памяти в Go
  • знание внутреннего устройства слайса
  • умение предсказывать побочные эффекты при передаче данных
  • понимание trade-off между копированием и ссылочной семантикой
  • способность объяснить поведение append и связанные с ним подводные камни

Для senior это базовая проверка - ожидается мгновенный и точный ответ без раздумий.

Типичные ошибки

  • Утверждение, что слайс передаётся по ссылке - это неверно, передаётся копия заголовка
  • Забывают, что изменение элементов через слайс видно вызывающему коду
  • Не учитывают, что append может создать новый массив
  • Путают массивы и слайсы в контексте копирования
  • Думают, что передача слайса всегда безопасна от копирования - это верно только для элементов, но не для заголовка

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью