Slice to dynamiczna tablica, podstawowa jednostka strukturalna przy pracy z tablicami w Go. Historycznie, języki programowania oferowały tablice o stałej wielkości lub cięższe struktury. Go zaimplementował slices jako wygodne narzędzie do przetwarzania kolekcji pamięci z automatycznym zarządzaniem jej rozmiarem i możliwością zmiany długości.
Problem polega na prawidłowym zarządzaniu pamięcią, obsłudze przypadków brzegowych (puste, nil, pełne slices) oraz na zrozumieniu różnicy między długością a pojemnością slice.
Rozwiązanie — prawidłowo korzystać z wbudowanych funkcji len(), cap(), oraz operować na slices zgodnie z konwencjami Go.
Przykład kodu:
var a []int // nil slice, len=0, cap=0 b := make([]int, 0) // pusty slice, len=0, cap=0 c := make([]int, 3, 5) // len=3, cap=5 c = append(c, 4, 5, 6) // cap zwiększy się automatycznie
Kluczowe cechy:
var s []int) nie przydziela pamięci w ogóle, różni się od pustego slice (make([]int, 0)) tylko wewnętrznie.Jakiej długości i pojemności będzie slice po append do nil slice?
Nil slice (var s []int) po append(s, 1) staje się slice o długości 1, pojemności 1 — Go sam przydziela pamięć.
var s []int s = append(s, 42) // s teraz [42], len=1, cap=1
Czy można uzyskać dostęp do pojemności slice równego nil?
Tak, w nil slice obie funkcje — len i cap — zwracają 0. Paniki nie będzie.
var s []int fmt.Println(len(s), cap(s)) // 0 0
Co się stanie przy próbie przypisania elementu przez indeks bez wcześniejszej alokacji pamięci do slice równego nil?
Panika index out of range, ponieważ slice nie ma elementów.
var s []int s[0] = 1 // panic: runtime error: index out of range
Zespół postanowił w serwerze Go wszędzie używać tylko var s []T, oczekując, że to zawsze będzie równoważne z make([]T, 0). W rezultacie niektóre marshalingi jsona zwracały null, a nie [].
Zalety:
Wady:
Użycie make([]T, 0, 100) do prealokacji, a następnie tylko append w pętli. W ten sposób minimalizowane są alokacje pamięci i często uzyskuje się lepszą wydajność.
Zalety:
Wady: