Sobes.tech
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 (капацитет се увећава)