Structuren in Go worden gekopieerd op waarde (diepe kopie van het eerste niveau, geneste structuren worden op dezelfde manier gekopieerd), terwijl slices op waarde worden gekopieerd, maar alleen de structuur wordt gekopieerd, niet de onderliggende gegevensarray: zowel het origineel als de kopie van de slice wijzen naar dezelfde backing array, dus een wijziging via één slice zal ook in de andere worden weerspiegeld, tenzij expliciet een kopie van de array wordt gemaakt via copy().
Voorbeeld van het kopiëren van een slice:
s1 := []int{1,2,3} s2 := s1 // wijzen naar dezelfde buffer! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Voor een kopie van de array: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 is onafhankelijk
Bij het kopiëren van structuren: als de structuur een pointerveld of sliceveld bevat, worden alleen de verwijzingen gekopieerd, niet de waarden.
Wat is de manier om een slice te "klonen" zodat de wijzigingen het origineel niet beïnvloeden?
Potentieel foutieve antwoord: Gewoon b := a doen. Juist:
copy gebruiken, een nieuwe slice van de vereiste lengte maken en de gegevens kopiëren:newS := make([]int, len(a)) copy(newS, a)
Verhaal
Beschrijving: Bij het dynamisch genereren van databasequery's werden de velden van de slice in de querystructuur gewijzigd zonder kopieën te maken. Bij herhaalde aanvragen waren de gegevens met elkaar verweven, wat onjuiste resultaten voor gebruikers opleverde.
Verhaal
Beschrijving: Bij parallelle gegevensverwerking werd een kopie van de structuur gemaakt door toewijzing en werd de slice in één goroutine uitgebreid, terwijl een andere originele slice tegelijkertijd werd gebruikt. Gegevens werden "overschreven", wat leidde tot onvoorspelbare bugs.
Verhaal
Beschrijving: Een bufferstructuur werd gebruikt, de gelijktijdige kopie via toewijzing hield geen rekening met geneste slices (shallow copy), wijzigingen op een plek beïnvloedden een andere buffer - uiteindelijk was het moeilijk om de bron van gegevenswijzigingen te traceren.