programowanieProgramista Go Backend

Opisz cechy kopiowania struktur i slice'ów w Go. Jak uniknąć nieoczekiwanych efektów podczas pracy z nimi?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

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.

Pytanie z pułapką

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:

  • Należy użyć copy, stworzyć nowy slice o odpowiedniej długości i skopiować dane:
newS := make([]int, len(a)) copy(newS, a)

Przykłady rzeczywistych błędów z powodu braku znajomości szczegółów tematu


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.