Junior
Kako funkcionišu slices u Go?
sobes.tech АИ
Одговор од АИ
Слајс је лагана облога над низом. Он не чува податке сам по себи, већ се позива на основни низ.
Структура слајса:
- Показивач на основни низ: Адреса првог елемента у меморији.
- Дужина (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 (капацитет се увећава)