Le fette sono solo descrittori (piccole strutture di dati simili a strutture) che, se non referenziate, verranno raccolte correttamente.
La matrice sottostante per una fetta (a cui punta descrittore a) invece è condivisa tra tutte le sezioni che vengono creati dai reslicing esso: citando la Go Language Specification: Slice Types:
Una fetta, una volta inizializzato, è sempre associato a una matrice sottostante che contiene i suoi elementi. Una slice quindi condivide lo storage con la sua matrice e con altre slice della stessa matrice; al contrario, gli array distinti rappresentano sempre una memoria distinta.
Pertanto, se almeno una sezione esiste o una variabile nell'array se una sezione è stata creata affettando l'array, non sarà raccolto.
Ufficiale Dichiarazione su questo:
Il post sul blog Go Slices: usage and internals Con Andrew Gerrand afferma chiaramente questo comportamento:
Come accennato in precedenza, ri-tagliare una fetta non fa una copia del matrice sottostante. L'array completo verrà mantenuto in memoria fino a quando non viene più fatto riferimento. Occasionalmente questo può far sì che il programma tenga tutti i dati in memoria quando è necessario solo un piccolo frammento di esso.
...
Poiché la fetta riferimento dell'array originale, finché la porzione viene mantenuto intorno al garbage collector non può rilasciare la matrice.
Torna al tuo esempio
Mentre la matrice sottostante non verrà liberata, si noti che se si aggiungono nuovi elementi alla coda, il built-in append
funzione di tanto in tanto potrebbe allocare un nuovo array e copiare gli elementi attuali al nuovo - ma la copia copierà solo gli elementi della slice e non l'intero array sottostante! Quando si verifica una tale riallocazione e copia, la matrice "vecchia" può essere raccolta tramite spazzatura se non esiste alcun altro riferimento.
Un'altra cosa molto importante è che se un elemento viene estratto dalla parte anteriore, la slice verrà riscritta e non conterrà un riferimento all'elemento popped, ma poiché l'array sottostante contiene ancora quel valore, il valore resterà anche in memoria (non solo l'array).Si consiglia che ogni volta che un elemento viene scoppiato o rimosso dalla coda (slice/array), lo azzeri sempre a (il suo rispettivo elemento nella sezione) in modo che il valore non rimanga nella memoria inutilmente. Ciò diventa ancora più critico se la tua sezione contiene puntatori a strutture di grandi dimensioni.
func PopFront(q *[]string) string {
r := (*q)[0]
(*q)[0] = "" // Always zero the removed element!
*q = (*q)[1:len(*q)]
return r
}
Per completare icza risposta, e per il tuo particolare caso in coda: la parte non raggiungibile della slice non sarà raccolta in background, tuttavia, quando "PushBack' un nuovo elemento e' q' è già pieno, verrà assegnata una nuova copia di 'q', e in questo caso, verranno ** copiati solo ** elementi raggiungibili **, quindi A, B e C non lo faranno. 'q' non crescerà per sempre con elementi irraggiungibili. – siritinga
@siritinga È vero, buon suggerimento. Grazie. Incorporato nella risposta con ulteriori informazioni importanti (come azzerare lo "slot" se un elemento viene rimosso). – icza