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
appendmůž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)