Le struct in Go vengono copiate per valore (deep copy di primo livello, le struct annidate vengono copiate secondo la stessa regola), mentre gli slice vengono copiati per valore, ma viene copiata solo la struttura e non l'array sottostante: sia l'originale che la copia dello slice puntano allo stesso backing array, quindi una modifica tramite uno slice si rifletterà nell'altro, a meno che non si faccia una copia esplicita dell'array tramite copy().
Esempio di copia di uno slice:
s1 := []int{1,2,3} s2 := s1 // puntatori allo stesso buffer! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Per la copia dell'array: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 è indipendente
Quando si copiano le struct: se la struct contiene un campo puntatore o un campo slice, vengono copiate solo le referenze, non i valori.
Qual è il modo per "clonare" uno slice in modo che le sue modifiche non influenzino l'originale?
Risposta potenzialmente errata: basta fare b := a. Corretto:
copy, creare un nuovo slice della lunghezza necessaria e copiare i dati:newS := make([]int, len(a)) copy(newS, a)
Storia
Descrizione: Durante la generazione di query al DB, si cambiavano dinamicamente i campi dello slice nella struct della query, senza fare copie. Durante le richieste successive i dati si sovrapponevano, restituendo risultati imprecisi per gli utenti.
Storia
Descrizione: Durante l'elaborazione parallela dei dati, si creava una copia della struct tramite assegnazione e si espandeva lo slice in una goroutine, utilizzando contemporaneamente un altro slice originale. I dati venivano "sovrascritti", portando a bug imprevedibili.
Storia
Descrizione: Si utilizzava una struct buffer, la copia simultanea tramite assegnazione non considerava gli slice annidati (shallow copy), le modifiche in un luogo influenzavano un altro buffer - alla fine era difficile rintracciare la fonte della modifica dei dati.