Dichiarare un array
Un tipo array si scrive [N]T: una lunghezza, poi un tipo di elemento. La lunghezza è fissata in fase di compilazione e fa parte del tipo.
Output:
[90 0 0 0 75] 5
Tue
[5]int [2 3 5 7 11]
["" "b" "" "d" ""]
Un array è sempre inizializzato del tutto. Gli elementi che non imposti contengono il valore zero del tipo dell'elemento: 0, "", false, nil.
Indici e limiti
Gli indici vanno da 0 a len(a)-1. Un indice costante fuori intervallo è un errore di compilazione. Un indice variabile fuori intervallo provoca un panic in fase di esecuzione.
var a [3]int
a[5] = 1 // compile error: invalid argument: index 5 out of bounds [0:3]
i := 5
a[i] = 1 // panic: runtime error: index out of range [5] with length 3
Scorrere un array
for i, v := range a visita ogni elemento in ordine. v è una copia dell'elemento, quindi assegnare un valore a v non modifica l'array. Scrivi invece tramite l'indice.
C'è un'altra sottigliezza tipica degli array: range su un valore array valuta subito una copia dell'array. Se il corpo del ciclo modifica gli elementi successivi, v mostra ancora i vecchi valori. Fare il range su &a o su a[:] evita la copia.
Gli array sono valori
Questa è la differenza principale rispetto agli array di C, Java o JavaScript. Assegnare un array copia ogni elemento. Anche passare un array a una funzione lo copia.
Output:
[1 2 3] [99 2 3]
[1 2 3]
[0 2 3]
La copia costa poco per gli array piccoli e molto per quelli grandi: passare un [1_000_000]int per valore copia otto megabyte. Passa un puntatore (*[N]T) o uno slice (a[:]) quando l'array è grande o quando la funzione deve modificarlo. Per accedere a un indice tramite un puntatore ad array non serve un * esplicito: a[0] funziona su un *[3]int.
Confrontare gli array e usarli come chiavi di una mappa
Gli array di elementi confrontabili supportano == e !=. Due array sono uguali quando ogni elemento è uguale. Questo li rende anche chiavi valide per una mappa, cosa che gli slice non sono.
Gli array di lunghezze diverse sono tipi diversi e non si possono proprio confrontare: [3]int{} == [4]int{} non compila (mismatched types [3]int and [4]int).
Array multidimensionali
Un array di array ti dà una griglia fissa. L'intera griglia è un unico blocco di memoria contiguo.
row[:] trasforma la riga [3]rune in uno slice []rune, che string() accetta.
Array e slice a confronto
Array [N]T | Slice []T | |
|---|---|---|
| Lunghezza | fissa, fa parte del tipo | cambia con append |
| Assegnazione e passaggio | copia tutti gli elementi | copia una piccola intestazione, condivide gli elementi |
| Valore zero | N elementi zero | nil, lunghezza 0 |
== | sì, elemento per elemento | solo con nil |
| Chiave di una mappa | sì | no |
| Uso tipico | dati di dimensione fissa: hash, coordinate, buffer | quasi tutto il resto |
In pratica incontrerai gli array soprattutto in pochi punti: sha256.Sum256 restituisce un [32]byte, nelle tabelle di lookup la cui dimensione non cambia mai e come memoria sottostante di uno slice. Fare lo slicing di un array con a[:] o a[1:3] crea uno slice che ne condivide la memoria; la pagina sugli slice spiega cosa comporta questa condivisione.
Convertire tra array e slice
Convertire uno slice in un array (Go 1.20) o in un puntatore ad array (Go 1.17) provoca un panic se lo slice è più corto della lunghezza dell'array: panic: runtime error: cannot convert slice with length 2 to array or pointer to array with length 3.
Errori comuni
- Aspettarsi che una funzione modifichi un array passato come argomento. Riceve una copia. Passa
*[N]To uno slice. - Usare un array dove serve uno slice.
[]int{1, 2}è uno slice,[2]int{1, 2}è un array. Una funzione che accetta[]intnon accetta un[2]int; passaa[:]. - Array grandi in un ciclo range.
for _, v := range bigArrayprima copia l'intero array. Fai il range su&bigArrayo su uno slice.
Domande frequenti
Come si dichiara un array in Go?
Scrivi la lunghezza tra parentesi quadre prima del tipo dell'elemento: var a [5]int crea cinque zeri. Con dei valori: a := [3]string{"x", "y", "z"}. Usa [...] per lasciare che sia il compilatore a contare: a := [...]int{1, 2, 3} ha tipo [3]int.
Qual è la differenza tra un array e uno slice in Go?
Un array ha una lunghezza fissa che fa parte del suo tipo ([3]int e [4]int sono tipi diversi) e viene copiato quando lo assegni o lo passi. Uno slice ([]int) è una vista su un array sottostante, con una lunghezza che può cambiare tramite append, e copiare uno slice copia solo la vista, non gli elementi. La maggior parte del codice Go usa gli slice.
Come ottengo la lunghezza di un array in Go?
Usa la funzione integrata len(a). Per un array è una costante nota in fase di compilazione, quindi puoi usarla nelle espressioni costanti. cap(a) restituisce lo stesso numero.
Si possono confrontare gli array in Go?
Sì, con == e !=, se il tipo degli elementi è confrontabile. Due array sono uguali quando tutti i loro elementi sono uguali. Gli array possono anche essere chiavi di una mappa. Gli slice non si possono confrontare con == (tranne che con nil); per loro usa slices.Equal.