Lekcje modułu (2/5)
Slices: idiomatyczna struktura
Wycinek to najczęściej używana struktura danych w Go: widok dynamiczny
nad bazową tablicą. Składnia: []T. W przeciwieństwie do tablic długość wynosi
nie jest częścią typu i możesz go rozwijać za pomocą append.
Anatomia plasterka
Wewnętrznie plasterek jest strukturą składającą się z trzech pól:
- wskaźnik do pierwszego elementu w tablicy bazowej
- a długość (
len): liczba widocznych elementów - pojemność (
cap): elementy dostępne od początku widoku na koniec podstawowej tablicy
s := []int{10, 20, 30}
fmt.Println(len(s), cap(s)) // 3 3Tworzenie
a := []int{1, 2, 3} // literal
b := make([]int, 3) // [0 0 0] len=3 cap=3
c := make([]int, 3, 10) // len=3 cap=10 (reserved)
var d []int // nil slice: len=0 cap=0, still usable with appendappend: zawsze przypisuj wynik
append dodaje elementy i zwraca nowy wycinek (potencjalnie
przydzielenie nowej tablicy, jeśli jej pojemność jest niewystarczająca):
s := []int{1, 2, 3}
s = append(s, 4) // [1 2 3 4]
s = append(s, 5, 6, 7) // append multiple elements
s = append(s, altra...) // concatenate another slice (spread)Wyrażenie plasterka s[a:b]
Wyodrębnia podkawałek z a (włącznie) do b (wyłącznie):
s := []int{10, 20, 30, 40, 50}
sub := s[1:4] // [20 30 40]
inizio := s[:2] // [10 20]
fine := s[3:] // [40 50]
intera := s[:] // [10 20 30 40 50]Pod-plasterki współdzielą podstawową tablicę z oryginalnym plasterkiem:
mutacje poprzez sub[i] = ... są widoczne również w s.
Pułapka: udostępnianie tablicy
s := []int{1, 2, 3, 4}
sub := s[0:2]
sub[0] = 99
fmt.Println(s) // [99 2 3 4] — modified!Aby uzyskać niezależną kopię, użyj copy lub append:
out := make([]int, len(sub))
copy(out, sub)Spróbuj
Utwórz plasterek s za pomocą [1, 2, 3] i użyj funkcji dołączania, aby dodać 4.
Pokaż wskazówkę
ZAWSZE przypisz wynik dołączenia z powrotem do `s`.
Rozwiązanie dostępne po 3 próbach
Użyj wyrażenia plasterka, aby wyodrębnić elementy z indeksu 1 włącznie do 3 na wyłączność (tj. [20, 30]).
Pokaż wskazówkę
Składnia: `s[start:end]`, `start` włącznie, `end` wyłącznie.
Rozwiązanie dostępne po 3 próbach
Który z nich jest błędnie napisany?
s := []int{1, 2, 3}
// (a) s = append(s, 4)
// (b) append(s, 4)Podsumowanie
[]T: dynamiczny widok tablicy; potrójny (ptr, len, cap).make([]T, len, cap)do wstępnej alokacji;var s []Tdla użytecznego kawałka zerowego.s = append(s, ...): ZAWSZE przypisuj wynik.s[a:b]dzieli podstawową tablicę:copy(...)dla niezależnych kopii.- Kawałek
nil= OK do odczytu/zakresu/dołączenia; zupełnie inna niż mapa zerowa.