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

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

Компании: Avito

Стек: Go

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

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

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

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

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

Слайс - это дескриптор, состоящий из трёх полей:

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

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

Важный нюанс: если внутри функции вы изменяете элементы слайса через индексацию, изменения будут видны в вызывающем коде, потому что оба заголовка указывают на один и тот же массив. Но если вы меняете сам заголовок (например, через append, который вызывает перераспределение), то внешний слайс не изменится.

На практике

На практике это означает:

  • Передача больших массивов в функцию - дорогая операция, так как копируется всё содержимое. Для больших данных лучше использовать указатели на массив или слайсы.
  • Слайсы - стандартный способ работы с последовательностями данных в Go, именно из-за дешёвой передачи заголовка.
  • Если нужно гарантировать, что функция не изменит данные, передавайте массив по значению или копируйте слайс внутри функции.
  • При работе с append внутри функции будьте осторожны: если ёмкости достаточно, изменения затронут исходный массив; если нет - будет создан новый массив, и внешний слайс останется без изменений.

Пример кода

GO
package main
import "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 внутри функции изменит внешний слайс - это верно только при достаточной ёмкости
  • Игнорирование того, что изменение элементов слайса внутри функции влияет на исходные данные
  • Путаница между копированием заголовка и копированием данных
  • Забывание, что массив можно передать по указателю, если нужно избежать копирования

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

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