Sobes.tech
Back to questions
Senior
7

Как устроен слайс в Go? Расскажите о внутренней реализации, подводных камнях и нюансах.

Companies where asked
техвил

Answer from AI

sobes.tech AI

Слайс в Go — это структура, которая описывает последовательный фрагмент массива. Внутренне слайс содержит три поля:

  • ptr — указатель на первый элемент массива, к которому относится слайс (не обязательно на первый элемент всего массива, а на первый элемент слайса);
  • len — длина слайса (количество элементов);
  • cap — ёмкость слайса (максимальное количество элементов, которые можно вместить, начиная с ptr).
type sliceHeader struct {
    ptr *ElementType
    len int
    cap int
}

Нюансы и подводные камни:

  • При создании слайса из массива или другого слайса, новый слайс ссылается на тот же underlying array. Изменения через один слайс отражаются в другом.
  • Если слайс увеличить по длине (через append), и ёмкости не хватает, создаётся новый массив, и данные копируются туда.
  • Из-за совместного использования массива может возникнуть утечка памяти: если слайс ссылается на большой массив, но используется только маленькая часть, весь массив не будет освобождён.
  • При передаче слайса в функцию копируется структура слайса (ptr, len, cap), но не копируются данные массива.

Пример:

arr := [5]int{1,2,3,4,5}
s1 := arr[1:3] // слайс с элементами {2,3}
s2 := s1[:4]   // расширяем длину до 4, но не больше cap
s2[3] = 10    // меняем элемент в исходном массиве
fmt.Println(arr) // [1 2 3 10 5]

Важно понимать, что слайсы — это удобный и эффективный способ работы с последовательностями, но нужно внимательно следить за их ёмкостью и временем жизни underlying array, чтобы избежать неожиданных ошибок и утечек памяти.