ProgrammazioneSviluppatore Go

Cosa sono le funzioni incorporate append, len e cap in Go, come funzionano a livello di linguaggio e quali pericoli nascosti degli slice sono associati al loro utilizzo?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Go, le funzioni incorporate append, len e cap giocano un ruolo chiave nel lavoro con gli slice.

  • len(slice) restituisce il numero di elementi nello slice.
  • cap(slice) restituisce la capacità dello slice — il numero massimo di elementi prima di allocare nuova memoria.
  • append(slice, elems ...T), quando la capacità è insufficiente, porta alla creazione di un nuovo array (e, di conseguenza, a un nuovo spazio di archiviazione), il che può inaspettatamente cambiare la semantica del passaggio dello slice.

Esempio:

arr := []int{1,2,3} arr2 := append(arr, 4) // arr2 può essere nello stesso o in un nuovo backing array, a seconda di cap(arr)

Sottigliezze:

  • Se si esegue append su uno slice che è stato "ritagliato" da un altro slice (o array originale), può verificarsi un side-effect: la modifica dei dati originali.
  • Quando si passano slice a funzioni, len/cap agiscono solo sulla parte "visibile".
  • Con append che supera la cap, viene creato un nuovo array, il vecchio non viene toccato.

Domanda trabocchetto

Cosa succederà se si "taglia" un pezzo dallo slice e si aggiunge un elemento tramite append? Questo influenzerà l'array originale?

Risposta: Se la cap lo consente, append scriverà l'elemento "in coda" all'array originale, e le modifiche saranno visibili attraverso tutti gli slice che fanno riferimento allo stesso array.

Esempio:

a := []int{1,2,3,4} b := a[:2] // [1 2], len=2, cap=4 b = append(b, 10) // cambia a: a -> [1, 2, 10, 4]

Esempi di errori reali


Storia

Nel team sono stati aggiunti elementi a uno slice figlio, e inaspettatamente sono stati modificati i dati nell'array padre — questo ha portato a disallineamenti nella logica aziendale e a bug difficili da debuggare nella distribuzione delle attività tra gli utenti.


Storia

Al secondo richiamo di append su uno slice grande, ci si aspettava che un nuovo array fosse sempre allocato nuovamente, ma di fatto diverse parti del sistema continuavano a lavorare con lo stesso "backing array", provocando una condizione di race e corruzione dei dati.


Storia

Uno sviluppatore ha allocato uno slice di dimensione fissa usando make, ma ha commesso un errore e ha scambiato gli argomenti: make([]int, cap, len). Di conseguenza, la logica basata sulla capacità ha inaspettatamente lavorato sulla lunghezza, causando panico quando si superavano i limiti s[0:len].