Struktury w Go są kopiowane przez wartość (głębokie kopiowanie pierwszego poziomu, zagnieżdżone struktury są kopiowane na tych samych zasadach), natomiast slice'y — również przez wartość, ale kopiowana jest tylko struktura, a nie wskazywana tablica danych: zarówno oryginał, jak i kopia slice'a wskazują na tę samą tablicę zaplecza, dlatego zmiana przez jeden slice odbije się na drugim, jeśli nie zrobimy jawnej kopii tablicy przez copy().
Przykład kopiowania slice'a:
s1 := []int{1,2,3} s2 := s1 // wskaźniki na ten sam bufor! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Aby skopiować tablicę: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 — niezależny
Przy kopiowaniu struktur: jeśli struktura zawiera pole-wskaźnik, pole-slice, to kopiowane są tylko odniesienia, a nie wartości.
Jaki sposób "sklonować" slice tak, aby jego zmiany nie dotyczyły oryginału?
Potencjalnie błędna odpowiedź: Po prostu zrobić b := a. Prawidłowo:
copy, stworzyć nowy slice o odpowiedniej długości i skopiować dane:newS := make([]int, len(a)) copy(newS, a)
Historia
Opis: Podczas generowania zapytań do bazy danych dynamicznie zmieniano pola slice'a w strukturze zapytania, nie robiąc kopii. Przy powtarzających się zapytaniach dane się pokrywały, dając niepoprawne wyniki dla użytkowników.
Historia
Opis: Podczas równoległej obróbki danych tworzono kopię struktury przez przypisanie i rozszerzali slice w jednym goroutine, równolegle używając innego oryginalnego slice'a. Dane "przerywały się", co prowadziło do nieprzewidywalnych błędów.
Historia
Opis: Używano struktury-bufora, równoczesne kopiowanie przez przypisanie nie uwzględniało zagnieżdżonych slice'ów (płytkie kopiowanie), zmiany w jednym miejscu dotykały innego buforu — w rezultacie trudno było śledzić źródło zmiany danych.