Go Slices - length, capability zmiana zawartości - przykład z dokumentacji

Go Slices - length, capability zmiana zawartości - przykład z dokumentacji
LU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 12
0

Cześć, może i proste pytanie, ale staram się zrozumieć jak to dokładnie działa.
Przykład z dokumentacji https://go.dev/tour/moretypes/11

Na górze tworzony jest Slice, czyli pod spodem tworzy się tablica z określoną liczbą elementów. (Dobrze rozumiem?)
Następnie są 3 kroki, które modyfikują slice np. s = s[:0]
Czyli pobieram elementy od pierwszego do zerowego i zapisuje jest w zmiennej s, która jest moim wycinkiem.
Czy przy zrobieniu czegoś takiego pierwotny stan tablicy się nie zmienia?
Czyli tego typu operacje nie mutują mojej tablicy?

Pytam bo wynik mnie troche dziwi.
Za każdym razem capacity jest takie samo czyli posiada pierwotną liczbę elementów 6.
A więc po 3 akcji przypisania wartości do zmiennej s nadal mogę na samym końcu odczytać jej oryginalny stan, jeżeli tylko wskaże odpowiednie indeksy elementów.

Dodatkowo czemu ostatnia akcja s = s[3:3] zmienia capability, a pozostałe nie.

Kopiuj
func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	printSlice(s)

	// Slice the slice to give it zero length.
	s = s[:0]
	printSlice(s)

	// Extend its length.
	s = s[:4]
	printSlice(s)

	// Drop its first two values.
	s = s[2:]
	printSlice(s)
}

func printSlice(s []int) {
	fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

Wynik tego kodu to

Kopiuj
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

99xmarcin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2420
1

Slice to struktura 3 wartości:

  • Wskaźnik na (początek) tablicy
  • Ile jest zajętych elementów (len)
  • Długość tablicy (cap).

W Javie odpowiada to size() i capacity() na List.
W C byśmy napisali:

Kopiuj
typedef struct {
  go_ref* data;
  int cap;
  int len;
} slice_t;

slice_t mkslice(int size) {
  slice_t t;
  t.data = malloc(sizeof(go_ref) * size);
  t.cap = size;
  t.len = 0;
  return t;
}

W Go Slice'y są nie tyle źle zaprojektowane co po prostu zjeb__e.

Jak robisz slice[:n] to po prostu mówisz re-użyj tablicy ale tak żeby len był ustawiony na n. Jeżeli zmienisz tak stworzony slice to zmieni się również oryginał.

Kopiuj
slice_t old = ...;
slice_t new = {
  .data = old.data
  .cap = old.cap
  .len = n
}

Jak mówisz slice[n:] to przesuwasz początek tablicy o n elementów, z tego powodu cap musi zostać zmniejszony żeby nie wywołać index out of bounds error (w Go inaczej się to nazywa).

Kopiuj
slice_t old = ...;
slice_t new = {
  .data = old.data + n
  .cap = old.cap - n
  .len = max(0, old.len - n)
}

Na sieci jest mnóstwo wpisów na ten temat wystarczy poszukać. Go to nie język dla przeciętnego kodera, poczekaj aż dojdziesz do deadlocków na corutynach puff...

LU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 12
0

Zanim napisałeś odpowiedź to już skumałem ten koncept, jednakże bardzo dziękuje za odpowiedź.
"Go to nie język dla przeciętnego kodera", dzięki wielkie, podbudowałeś mnie :)
Zakładam, że chciałeś w ten sposób powiedzieć abym zrezygnował z dalszej nauki, uznając po moim pytaniu, że to nie dla mnie.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.