Junior
Как работят слайсовете в Go?
sobes.tech AI
Отговор от AI
Слайсът е лека обвивка над масив. Той не съхранява данни сам по себе си, а се позовава на основния масив.
Структурата на слайса:
- Посочване към основния масив: Адресът на първия елемент в паметта.
- Дължина (Length): Броят на елементите в слайса.
- Капацитет (Capacity): Броят на елементите в основния масив, достъпни от посочването на слайса.
// Пример за обявяване на слайс
var s []int
s = append(s, 1, 2, 3) // Добавяне на елементи
// Вътрешно представяне на слайса s (опростено)
// struct SliceHeader {
// Data uintptr // Посочване към основния масив
// Len int // Дължина на слайса
// Cap int // Капацитет на слайса
// }
- При създаване на слайс чрез
make([]T, length, capacity)се създава основен масив с посочения капацитет и слайс, който се позовава на него с посочената дължина. - При използване на срез върху масив или друг слайс (например,
arr[low:high:max]) се създава нов слайс, който се позовава на същата област в паметта на основния масив, но с друг посочващ, дължина и капацитет. - Операцията
appendможе да доведе до преразпределение на паметта. Ако текущият капацитет не е достатъчен за добавяне на нови елементи, Go създава нов, по-голям основен масив, копира в него елементите от стария масив и актуализира посочването на слайса към новия масив. Това се нарича реалаокация. Растежът на капацитета при append е експоненциален (удвоява се до определен размер, след което растежът се забавя). - Слайсовете се предават по стойност, но тъй като те съдържат посочване към основния масив, промените в елементите на слайса (чрез индекс) ще бъдат видими във всички слайсове, които се позовават на същия основен масив.
- Промяната на дължината на слайса чрез срез не засяга основния масив, но може да ограничи достъпа до част от данните на основния масив.
Таблица: Сравнение на Length и Capacity
| Характеристика | Дължина (Length) | Капацитет (Capacity) |
|---|---|---|
| Определение | Фактическото количество елементи в слайса | Максималното количество елементи, които могат да бъдат в слайса без преразпределение |
| Достъп | Използва се за достъп до елементите (s[i]) | Определя колко още елементи могат да бъдат добавени чрез append преди реалаокация |
| Получаване | len(s) |
cap(s) |
// Пример за работа с капацитет и дължина
s := make([]int, 0, 5) // Дължина 0, капацитет 5
fmt.Println(len(s), cap(s)) // 0 5
s = append(s, 1, 2) // Добавяне на 2 елемента
fmt.Println(len(s), cap(s)) // 2 5
s = append(s, 3, 4, 5, 6) // Добавяне още 4 елемента, необходима е реалаокация
fmt.Println(len(s), cap(s)) // 6 10 (капацитетът се увеличи)