Слайсы vs массивы: внутреннее устройство и производительность
Вопрос
В чем разница между массивами и слайсами в Go? Как устроены слайсы внутри? Какие есть подводные камни при работе со слайсами?
Ответ
Массивы: - Фиксированный размер, известный на этапе компиляции - Значения (копируются при присваивании) - Тип включает размер: [3]int ≠ [4]int Слайсы: - Ссылочный тип (header + указатель на массив) - Динамический размер - Содержат: pointer, length, capacity - При превышении capacity создается новый массив
// Массив
var arr [3]int = [3]int{1, 2, 3}
// Слайс
var slice []int = []int{1, 2, 3}
// Внутреннее устройство слайса
type SliceHeader struct {
Data uintptr // указатель на данные
Len int // длина
Cap int // емкость
}
// Подводный камень - shared underlying array
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[1:3] // {2, 3}
s2[0] = 999 // s1 = {1, 999, 3, 4, 5}!
// Массив
var arr [3]int = [3]int{1, 2, 3}
// Слайс
var slice []int = []int{1, 2, 3}
// Внутреннее устройство слайса
type SliceHeader struct {
Data uintptr // указатель на данные
Len int // длина
Cap int // емкость
}
// Подводный камень - shared underlying array
s1 := []int{1, 2, 3, 4, 5}
s2 := s1[1:3] // {2, 3}
s2[0] = 999 // s1 = {1, 999, 3, 4, 5}!
Дополнительные вопросы
Как работает append()? Когда происходит перевыделение памяти?