Sobes.tech
Junior

Jak fungují slices v Go?

sobes.tech AI

Odpověď od AI

Slicing je lehká obálka nad polem. Samo o sobě neukládá data, pouze odkazuje na základní pole.

Struktura slicingu:

  • Ukazatel na základní pole: Adresa prvního prvku v paměti.
  • Délka (Length): Počet prvků v slicingu.
  • Kapacita (Capacity): Počet prvků v základním poli dostupných od ukazatele slicingu.
// Příklad deklarace slicingu
var s []int
s = append(s, 1, 2, 3) // Přidání prvků

// Vnitřní reprezentace slicingu s (zjednodušeně)
// struct SliceHeader {
//     Data uintptr // Ukazatel na základní pole
//     Len int      // Délka slicingu
//     Cap int      // Kapacita slicingu
// }
  • Při vytváření slicingu pomocí make([]T, length, capacity) se vytváří základní pole s danou kapacitou a slicing, který na něj odkazuje s danou délkou.
  • Při použití řezu na pole nebo jiném slicingu (například arr[low:high:max]) se vytváří nový slicing, který odkazuje na stejnou oblast paměti základního pole, ale s jiným ukazatelem, délkou a kapacitou.
  • Operace append může vést k přerozdělení paměti. Pokud aktuální kapacita nestačí pro přidání nových prvků, Go vytvoří nové větší základní pole, zkopíruje do něj prvky starého pole a aktualizuje ukazatel slicingu na nové pole. To se nazývá reallokace. Růst kapacity při append je exponenciální (zdvojuje se do určité velikosti, poté se růst zpomaluje).
  • Slicingy jsou předávány hodnotou, ale protože obsahují ukazatel na základní pole, změny prvků slicingu (přes index) budou viditelné ve všech slicingu odkazujících na stejné základní pole.
  • Změna délky slicingu přes řez neovlivňuje základní pole, ale může omezit přístup k části dat základního pole.

Tabulka: Porovnání Length a Capacity

Charakteristika Délka (Length) Kapacita (Capacity)
Definice Skutečný počet prvků v slicingu Maximální počet prvků, které mohou být v slicingu bez přerozdělení
Přístup Používá se pro přístup k prvkům (s[i]) Určuje, kolik dalších prvků lze přidat přes append před reallokací
Získání len(s) cap(s)
// Příklad práce s kapacitou a délkou
s := make([]int, 0, 5) // Délka 0, kapacita 5
fmt.Println(len(s), cap(s)) // 0 5

s = append(s, 1, 2) // Přidání 2 prvků
fmt.Println(len(s), cap(s)) // 2 5

s = append(s, 3, 4, 5, 6) // Přidání dalších 4 prvků, potřeba reallokace
fmt.Println(len(s), cap(s)) // 6 10 (kapacita se zvětšila)