ProgrammazioneSviluppatore Go

Come funziona copy() in Go nella copia di slice? Quali sono le peculiarità, le limitazioni e gli effetti inaspettati legati alla crescita della lunghezza e della capacità dello slice? Cosa succede quando si sovrappongono slice l'uno sull'altro e si cerca di copiarli in sovrapposizione?

Supera i colloqui con l'assistente IA Hintsage

Risposta

La funzione copy(dst, src []T) int copia gli elementi da src a dst.

  • Restituisce il numero di elementi copiati: min(len(dst), len(src)).
  • La copia avviene per indice: gli elementi src[i] vengono copiati in dst[i].
  • Vengono copiati i contenuti (valori), non i puntatori agli oggetti.

Peculiarità e limitazioni:

  • Se gli slice si sovrappongono (ad esempio, uno è un sottoarray dell'altro), la copia avviene come se prima venisse preso un frammento dei valori originali e poi copiato (non ci sono garanzie di correttezza in caso di sovrapposizione).
  • Se dst ha una lunghezza minore di src, verrà copiata solo la quantità di dati consentita dalla lunghezza di dst.
  • Se dst ha una capacità maggiore della lunghezza, copy allarga lo slice? — No, solo len(dst) è considerato obiettivo. Per allargare — usa append in precedenza.

Esempio:

a := []int{1,2,3,4,5} b := make([]int, 3) copy(b, a) // b: [1 2 3]

Sovrapposizione:

x := []int{1,2,3,4} copy(x[1:], x[:3]) // [1 1 2 3]

Domanda insidiosa

copy() può essere usato per aumentare la lunghezza dello slice? Cosa succede se si passa a copy uno slice di destinazione con una maggiore capacità, ma una lunghezza minore di quella richiesta?

Risposta:

  • copy() non cambia la lunghezza dello slice di destinazione — copia solo fino a len(dst)
  • Se dst ha una capacità maggiore della lunghezza, allargalo prima tramite dst = dst[:newLen], poi usa copy()

Esempio, spesso non ovvio:

a := []int{1,2,3} b := make([]int, 0, 5) copy(b, a) // b rimarrà vuoto, poiché len(b)==0 b = b[:len(a)] copy(b, a) // ora b: [1,2,3]

Esempi di errori reali dovuti all'ignoranza delle peculiarità del tema


Storia

Nel progetto venivano copiati dati da uno slice all'altro, contando sul fatto che copy avrebbe automaticamente allargato la lunghezza di dst a quella necessaria. Questo non è successo, gli elementi non sono stati copiati, risultando in dati nulli nella risposta API. L'errore è stato scoperto solo dopo aver confrontato le lunghezze degli slice — il problema era che dst aveva una grande capacità, ma lunghezza pari a 0.


Storia

Una parte del microservizio lavorava con slice sovrapposti, calcolando erroneamente che copy avrebbe sempre funzionato correttamente. Di conseguenza, copiare in avanti distruggeva i dati originali, causando bug "invisibili" durante il lavoro con i buffer. È stato risolto utilizzando un buffer temporaneo (copy(tmp, src), poi copy(dst, tmp)).


Storia

Un ingegnere ha ottimizzato un array utilizzando copy per ordinare i dati tra gli slice. Si aspettava che copy correggesse la lunghezza di dst. Si è scoperto che non avveniva e sono emerse panico e accessi a dati significativi — si è dimenticato di modificare correttamente la lunghezza dello slice prima della copia.