Condivisione della tecnologia

[Go series] array, slice e mappa

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Collega il precedente e il successivo

Abbiamo introdotto se e per nel nostro articolo precedente. Questo non dovrebbe essere messo in pratica. Facciamo pratica su come usarlo.continue Istruzione per calcolare la somma dei numeri pari entro 100. Mentre scriviamo il codice,continueci aiuterà a saltare alcune iterazioni che non sono necessarie, ad esempio, in questo esempio salteremo tutti i numeri dispari.

  1. sum := 0
  2. for i := 1; i < 100; i++{
  3. if i & 1 == 0 {
  4. continue
  5. }
  6. sum += i
  7. }
  8. fmt.Println("the sum is",sum)

Inizia ad imparare

Nella programmazione, spesso abbiamo a che fare con un insieme di elementi dello stesso tipo e questi insiemi di elementi sono rappresentati da strutture dati specifiche nel linguaggio Go. Oggi ti presenterò in dettaglio diversi tipi di raccolta in Go: array, slice e map.

vettore

Innanzitutto, iniziamo con gli array. L'array è la struttura dati più elementare di Go. È una sequenza di elementi dello stesso tipo a lunghezza fissa. Una volta dichiarato un array, la sua lunghezza non può essere modificata. La dichiarazione e l'inizializzazione degli array sono molto semplici,

Dichiarare l'array

Quando si dichiara un array, è necessario specificare il tipo e la lunghezza dell'array. Ecco come viene dichiarato un array:

var arrayName [arrayLength]elementType

Ad esempio, dichiara un array di numeri interi di lunghezza 5:

var numbers [5]int
inizializza l'array

Puoi inizializzare un array in vari modi:

  • Utilizza l'inizializzazione letterale:
var numbers = [5]int{1, 2, 3, 4, 5}
  • utilizzo:=Breve dichiarazione:
numbers := [5]int{1, 2, 3, 4, 5}
  • Deduci automaticamente la lunghezza dell'array:
numbers := [...]int{1, 2, 3, 4, 5}
  • Specificare l'inizializzazione dell'indice:
numbers := [5]int{0: 1, 4: 5}

Caratteristiche degli array

  • Lunghezza fissa: La lunghezza dell'array viene determinata al momento della dichiarazione e non può essere modificata successivamente.
  • elementi dello stesso tipo: Gli array possono contenere solo elementi dello stesso tipo.
  • allocazione di memoria in modo contiguo: Gli elementi dell'array vengono allocati in modo contiguo in memoria, il che rende l'accesso agli elementi dell'array molto efficiente.

Accedere agli elementi dell'array

Puoi accedere agli elementi di un array per indice, a partire da 0:

value := numbers[2] // 获取索引为 2 的元素

Matrice trasversale

Puoi usareforPassa in rassegna tutti gli elementi di un array:

  1. for i, value := range numbers {
  2. fmt.Printf("Index: %d, Value: %dn", i, value)
  3. }

lunghezza dell'array

Puoi usare il built-inlenFunzione per ottenere la lunghezza di un array:

length := len(numbers)

valore zero dell'array

Se un array non viene inizializzato esplicitamente, i suoi elementi vengono automaticamente impostati sul valore zero del relativo tipo. Ad esempio, il valore zero di un array di numeri interi è 0:

var numbers [5]int // 所有元素都是 0

Array multidimensionali

Il linguaggio Go supporta anche array multidimensionali. Quello che segue è un esempio di dichiarazione e inizializzazione di un array di numeri interi 2x3:

  1. var matrix [2][3]int
  2. matrix = [2][3]int{{1, 2, 3}, {4, 5, 6}}

Limitazioni degli array

Poiché la lunghezza dell'array è fissa, in alcuni casi potrebbe non essere molto flessibile. Se hai bisogno di una raccolta di lunghezza variabile, puoi utilizzare le sezioni.

fetta

Il prossimo è slice, che è un tipo integrato più flessibile che può essere pensato come un array dinamico. La lunghezza della sezione è variabile e viene creata in base a un array, offrendo maggiore comodità. Ecco come dichiarare e inizializzare una porzione:

  1. s := make([]int, 3) // 创建一个长度为3的整型切片
  2. s[0] = 1 // 切片元素赋值
  3. s[1] = 2
  4. s[2] = 3
  5. s = append(s, 4) // 向切片追加元素

Nel linguaggio Go, sebbene gli array e le slice siano entrambi utilizzati per archiviare una serie di elementi dello stesso tipo, presentano differenze significative nell'allocazione della memoria, nella variabilità delle dimensioni e nell'utilizzo. Ecco le principali differenze tra array e slice:

variabilità dimensionale

  • vettore : La dimensione di un array viene determinata al momento della dichiarazione e non può essere modificata successivamente.La dimensione di un array fa parte del suo tipo, quindi[3]intE[4]intsono di tipi diversi.
  • fetta : le porzioni sono dinamiche e possono aumentare o ridursi in fase di esecuzione.La dimensione di una fetta non fa parte della sua tipologia, quindi[]intÈ il tipo comune per tutte le sezioni intere.

allocazione della memoria

  • vettore : Gli array sono tipi di valore e quando un array viene passato come parametro di funzione, viene passata una copia del suo valore. Ciò significa che le modifiche all'array all'interno della funzione non influiscono sull'array originale.
  • fetta : Slice è un tipo di riferimento, che contiene un puntatore all'array sottostante, la lunghezza e la capacità della slice. Quando una fetta viene passata come parametro di una funzione, viene passata una copia del puntatore, quindi le modifiche alla fetta all'interno della funzione influenzeranno la fetta originale.

inizializzazione

  • vettore: Quando si inizializza un array, è necessario specificarne la dimensione e i valori degli elementi possono essere assegnati immediatamente.
  • fetta: le fette possono essere passate attraverso valori letterali,makeFunzione o sezione da un array da inizializzare, nessuna dimensione specificata.

Codice d'esempio

Ecco alcuni esempi di inizializzazione per array e sezioni:

  1. // 数组
  2. var arr [3]int = [3]int{1, 2, 3}
  3. // 切片
  4. var slice []int = []int{1, 2, 3}
  5. // 或者使用 make 函数
  6. slice := make([]int, 3)

Differenze funzionali

  • vettore: Poiché la dimensione è fissa, la dimensione dell'array è nota in fase di compilazione, il che rende possibile allocare memoria per l'array sullo stack e la complessità temporale dell'accesso agli elementi dell'array è O(1).
  • fetta: L'affettatura offre maggiore flessibilitàappend La funzione aggiunge elementi o ottiene sottosezioni tramite operazioni di sezionamento.L'array sottostante della fetta può essere allocato sull'heap e anche la complessità temporale dell'accesso agli elementi della fetta è O (1), maappendPuò comportare la riallocazione dell'array sottostante, che in genere è un'operazione O(n).

Mappatura

Infine, diamo un'occhiata alla mappatura. Una mappa è un array associativo in Go che associa le chiavi ai valori. Le chiavi della mappa possono essere di qualsiasi tipo supportato dall'operatore di uguaglianza, come numeri interi, numeri in virgola mobile, stringhe, puntatori, interfacce (purché i valori contenuti nell'interfaccia siano confrontabili), strutture e array. Il valore mappato può essere di qualsiasi tipo.

Dichiarazione e inizializzazione

dichiarare la mappa

La sintassi per dichiarare una mappa è la seguente:

var mapName map[keyType]valueType

Ad esempio, dichiara una mappa con chiavi come stringhe e valori come numeri interi:

var scores map[string]int
Inizializza la mappa

Dopo aver dichiarato la mappa, devi passaremakefunzione per inizializzarlo in modo che possa essere utilizzato:

scores = make(map[string]int)

In alternativa, puoi utilizzare una breve dichiarazione e inizializzare:

scores := make(map[string]int)

Puoi anche utilizzare i valori letterali per l'inizializzazione al momento della dichiarazione:

  1. scores := map[string]int{
  2. "alice": 90,
  3. "bob": 85,
  4. "charlie": 88,
  5. }

Caratteristiche della mappa

  • unicità fondamentale: In una mappa, ogni chiave è unica. Se provi a inserire una chiave esistente, verrà aggiornato il valore corrispondente alla chiave.
  • disturbo:map non è ordinata e l'ordine degli elementi può essere diverso ogni volta che la mappa viene ripetuta.
  • dimensione dinamica:La dimensione della mappa è dinamica, puoi aggiungere o rimuovere coppie chiave-valore secondo necessità.
  • tipologia di riferimento: Map è un tipo di riferimento Quando passi map a una funzione, ciò che effettivamente passi è un puntatore alla struttura dati sottostante.

Mappa operativa

Aggiungi elemento
scores["alice"] = 90
Ottieni elemento
value := scores["alice"]

Se la chiave non esiste, verrà restituito un valore zero per quel tipo di valore.

Controlla se la chiave esiste

Puoi usare l'espressione virgola -ok per verificare se la chiave esiste nella mappa:

  1. value, exists := scores["alice"]
  2. if exists {
  3. // 键存在
  4. } else {
  5. // 键不存在
  6. }
Elimina elemento

utilizzodeleteLa funzione può rimuovere una coppia chiave-valore dalla mappa:

delete(scores, "alice")

Se la chiave non esiste,deleteLa funzione non fa nulla.

Attraversa la mappa

utilizzoforUn ciclo può attraversare tutte le coppie chiave-valore nella mappa:

  1. for key, value := range scores {
  2. fmt.Printf("%s: %dn", key, value)
  3. }

valore zero della mappa

Il valore zero della mappa ènil .unonil Una mappa non ha una struttura dati sottostante e non può aggiungere elementi.Prima di aggiungere elementi alla mappa, è necessario utilizzaremakeInizializzalo.

lunghezza della mappa

Puoi usare il built-inlenFunzione per ottenere il numero di coppie chiave-valore nella mappa:

length := len(scores)

tipo di chiave della mappa

Le chiavi della mappa possono essere di qualsiasi tipo comparabile, come numeri interi, numeri in virgola mobile, stringhe, puntatori, interfacce (purché i valori contenuti nell'interfaccia siano comparabili), strutture, array, ecc. Porzioni, mappe e funzioni non possono essere utilizzate come chiavi di mappa poiché questi tipi non supportano i confronti di uguaglianza.

Facile commettere errori

Nel linguaggio Go, array, slice e mappe sono tre strutture dati comunemente utilizzate, ognuna delle quali ha caratteristiche e considerazioni diverse. Ecco alcuni punti da notare quando li si utilizza:

Vettore

  • Evitare di utilizzare array troppo grandi poiché occupano molto spazio nello stack e potrebbero causare un overflow dello stack.
  • Gli array vengono utilizzati quando è richiesta una raccolta di dati di dimensione fissa.

Fetta

  • Potrebbe verificarsi una riallocazione della memoria quando la suddivisione viene estesa. Provare a preassegnare una capacità sufficiente per evitare espansioni frequenti.
  • Evita di utilizzare slice troppo grandi poiché possono occupare molto spazio nell'heap.
  • Si noti che il valore zero della fetta ènil, deve essere inizializzato prima dell'uso.

carta geografica

  • Il valore zero della mappa ènilnilLa mappa non può essere utilizzata per archiviare coppie chiave-valore e deve essere inizializzata prima dell'uso.
  • In un ambiente simultaneo, le operazioni di lettura e scrittura sulla mappa non sono thread-safe e devono essere protette utilizzando blocchi mutex o altri meccanismi di sincronizzazione.
  • utilizzodeleteL'eliminazione di una chiave che non esiste non genera un errore, ma è sicuro verificare se la chiave esiste.