Introduzione
Nell’informatica, una loop è una struttura di codice che ripete l’esecuzione di un determinato pezzo di codice, spesso finché una certa condizione non è soddisfatta. L’utilizzo di loop nel programmazione consente di automatizzare e ripetere più volte compiti simili. Immaginate di avere una lista di file da elaborare o di volere contare il numero di righe in un articolo. Utilizzereste un loop nel vostro codice per risolvere questo tipo di problemi.
In Go, il ciclo for
implementa l’esecuzione ripetuta del codice in base a un contatore o una variabile di loop. A differenza di altre lingue di programmazione che hanno costruttori di loop multipli come while
, do
ecc., Go ha solo il ciclo for
. Questo serve a rendere il vostro codice più chiaro e leggibile, in quanto non dovete preoccuparvi di strategie multiple per ottenere lo stesso costrutto di loop. Questa leggibilità migliorata e la riduzione della carica cognitiva durante lo sviluppo renderà anche il vostro codice meno soggetto ad errori rispetto alle altre lingue.
In questo tutorial, imparerete come funziona il ciclo for
in Go, inclusi i tre principali tipi di sue utilizzi. Inizieremo mostrando come creare diversi tipi di cicli for
, seguiti da come iterare attraverso tipi di dati sequenziali in Go. Concluderemo spiegando come usare i cicli annidati.
Declare ForClause e Loop condizionale
Per tenere conto di una varietà di casi d’uso, ci sono tre modi diversi per creare loop for
in Go, ognuno con le sue proprie capacità. Questi sono creare un loop for
con una Condizione, una ForClause o una RangeClause. In questa sezione, spiegheremo come dichiarare e utilizzare le varianti ForClause e Condizione.
Ora guardiamo come possiamo utilizzare un loop for
con la ForClause.
Un loop ForClause è definito come avente un’istruzione iniziale, seguita da una condizione, e poi da un’istruzione post. Questi sono disposti nella seguente sintassi:
for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
[Action]
}
Per spiegare cosa fanno i componenti precedenti, guardiamo un loop for
che incrementa attraverso un range di valori specificato utilizzando la sintassi ForClause:
Ora analizziamo questo loop e identifichiamo ogni parte.
La prima parte dell’iteratore è i := 0
. Questa è l’istruzione iniziale:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Essa dichiara una variabile chiamata i
e imposta il valore iniziale a 0
.
Poi abbiamo la condizione:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
In questa condizione, abbiamo detto che mentre i
è minore del valore di 5
, il loop deve continuare a iterare.
Infine, abbiamo l’istruzione post:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
Nella dichiarazione del ciclo, incrementiamo la variabile di iterazione i
di uno ad ogni iterazione utilizzando l’operatore i++
di incremento.
Quando facciamo partire questo programma, l’output è così:
Output0
1
2
3
4
Il ciclo è stato eseguito 5 volte. All’inizio abbiamo impostato i
a 0
, poi abbiamo controllato se i
era minore di 5
. Poiché il valore di i
era inferiore a 5
, il ciclo è stato eseguito e l’azione di fmt.Println(i)
è stata eseguita. Dopo aver finito il ciclo, la dichiarazione post di i++
è stata chiamata, e il valore di i
è stato incrementato di 1.
Nota: Tenga presente che nella programmazione tendiamo a iniziare a partire dall’indice 0, per questo motivo sebbene vengano stampati 5 numeri, vanno da 0 a 4.
Non siamo limitati a partire da 0 o a terminare con un valore specifico. Possiamo assegnare qualsiasi valore alla nostra dichiarazione iniziale e anche fermarci con qualsiasi valore nella dichiarazione post. Questo ci consente di creare qualsiasi range desiderato per iterare:
Qui, l’iterazione parte da 20 (incluso) e termina con 25 (escluso), quindi l’output è così:
Output20
21
22
23
24
Possiamo anche usare la nostra dichiarazione post per incrementare con differenti valori. È simile all’step
in altre lingue:
Prima di tutto, usiamo una dichiarazione post con un valore positivo:
for i := 0; i < 15; i += 3 {
fmt.Println(i)
}
In questo caso, il ciclo for
è impostato in modo da stampare i numeri da 0 a 15, ma con un incremento di 3, quindi viene stampato solo ogni terzo numero, così:
Output0
3
6
9
12
Potremmo anche usare un valore negativo per l’argomento dell’istruzione post della dichiarazione per iterare in direzione inversa, ma dovremmo adattare correttamente gli argomenti dell’istruzione iniziale e condizionale:
In questo caso, abbiamo impostato i
con un valore iniziale di 100
, utilizzato la condizione di i < 0
per fermarsi al 0
, e l’istruzione post decrementa il valore di 10 con l’operatore -=
. La loop comincia al 100
e finisce al 0
, diminuendo di 10 con ogni iterazione. Puoi vedere questo avvenire nell’output:
Output100
90
80
70
60
50
40
30
20
10
Puoi anche escludere l’istruzione iniziale e l’istruzione post dal linguaggio for
sintassi, e solo usare la clausola condizionale. Questo è quello che si chiama un Loop condizionale:
i := 0
for i < 5 {
fmt.Println(i)
i++
}
Questo volta, abbiamo dichiarato la variabile i
separata dalla precedente linea di codice. La loop ha solo una clausola condizionale che verifica se i
è meno di 5
. Se la condizione valuta come true
, la loop continuerà ad eseguire le iterazioni.
Alcuni casi potrebbero non sapere quante iterazioni saranno necessarie per completare un determinato compito. In quel caso, puoi omettre tutte le istruzioni e usare la parola chiave break
per uscire dall’esecuzione:
for {
if someCondition {
break
}
// fare azione qui
}
Un esempio di questo potrebbe essere se stai leggendo da un’estensione indefinita come un buffer e non sai quando sarà terminata la lettura:
Nell’codice precedente, buf := bytes.NewBufferString("uno
dichiama un buffer con alcuni dati. Perché non siamo sicuri di quando il buffer finirà di leggerli, abbiamo creato un ciclo
due
tre
quattro
")for
senza clausola. Dentro il ciclo for
, usiamo line, err = buf.ReadString
per leggere una linea dal buffer e controllare se c’è stato un errore durante la lettura del buffer. Se c’è stato un errore, risolveremo l’errore e utilizzeriamo il comando
")break
per uscire dal ciclo . In questa sezione abbiamo imparato come dichiarare un ForClause loop e come usarlo per iterare su un intervallo predefinito di valori. Abbiamo anche imparato come usare un LoopCondition per iterare finché una condizione specifica non viene raggiunta.
Nel prossimo capitolo, si apprenderanno come usare la clausola RangeClause per iterare attraverso tipi di dati sequenziali.
Looping Through Sequential Data Types with RangeClause
Nella lingua di Go è comune usare i cicli for
per iterare su tipi di dati sequenziali o collezioni come slice, array e stringhe. Per fare questo più facilemente possiamo usare la sintassi for
con il RangeClause. Mentre puoi iterare su tipi di dati sequenziali usando la sintassi ForClause, la RangeClause è più pulita e facile da leggere. Prima di guardarci come usare la RangeClause, guarda come si fa usando la ForClause:
Questo sarà il risultato dell’output che stampa ogni elemento della slice:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i := 0; i < len(sharks); i++ {
fmt.Println(sharks[i])
}
}
Ora, vediamo come iterare attraverso una lista usando la RangeClause:
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
Nel caso precedente abbiamo stampato ogni elemento della lista. Sebbene abbiamo usato le variabili i
e shark
, potremmo chiamare qualsiasi altro nome valido per le variabili e avremmo ottenuto lo stesso output:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(i, shark)
}
}
Quando usiamo range
su una slice, viene sempre restituito un valore. Il primo valore sarà l’indice che la corrente iterazione del loop è al momento, e il secondo è il valore all’indice. Nel caso prima, per la prima iterazione, l’indice era 0
e il valore era hammerhead
.
Output0 hammerhead
1 great white
2 dogfish
3 frilled
4 bullhead
5 requiem
Alcuni volti, abbiamo solo il valore all’interno degli elementi della slice e non l’indice. Se modifichiamo quello che precede il codice per stampare solo il valore, riceverà un errore di compilazione:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for i, shark := range sharks {
fmt.Println(shark)
}
}
Outputsrc/range-error.go:8:6: i declared and not used
Perché i è dichiarato nell’loop for
, ma non usato, il compilatore risponderà con l’errore di i dichiarato e non usato
. Questo è lo stesso errore che riceveremmo in Go ogni volta che dichiariamo una variabile e non la usiamo.
Due a questo, Go ha l’identificatore vuoto che è un underscore (_
). Nell’loop for
, puoi usare l’identificatore vuoto per ignorare qualsiasi valore restituito dal operatore range
. In questo caso, vogliamo ignorare l’indice, che è il primo argomento restituito.
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for _, shark := range sharks {
fmt.Println(shark)
}
}
Outputhammerhead
great white
dogfish
frilled
bullhead
requiem
Questo mostra che l’loop dell’slice di stringhe è iterato attraverso ogni elemento del slice senza l’indice.
Puoi anche usare range
per aggiungere elementi alla lista:
package main
import "fmt"
func main() {
sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
for range sharks {
sharks = append(sharks, "shark")
}
fmt.Printf("%q\n", sharks)
}
Output['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']
Qui abbiamo aggiunto un placeholder stringa di "shark"
per ogni elemento della lunghezza del sharks
slice.
Nota che non abbiamo dovuto usare l’identificatore vuoto _
per ignorare qualsiasi valore restituito dall’operatore range
. Go consente di lasciar fuori completamente la parte dichiarativa del range
se non ne avessimo bisogno di usarne due.
Possiamo anche usare l’operatore range
per riempirvi valori di una slice:
package main
import "fmt"
func main() {
integers := make([]int, 10)
fmt.Println(integers)
for i := range integers {
integers[i] = i
}
fmt.Println(integers)
}
Nella prima parte dell’esempio, la slice integers
è stata inizializzata con dieci valori vuoti, ma il ciclo for
loop imposta tutti i valori della lista come segue:
Output[0 0 0 0 0 0 0 0 0 0]
[0 1 2 3 4 5 6 7 8 9]
La prima volta che stampiamo il valore della slice integers
, vedremo tutti i zero. Poi abbiamo iterato attraverso ogni indice e settato il valore alla corrente posizione. Quindi quando stampiamo il valore di integers
per la seconda volta, mostraremo che tutti ora hanno un valore di 0
da 0
fino a 9
.
Possiamo anche usare l’operatore range
per iterare attraverso ogni carattere in una stringa:
OutputS
a
m
m
y
Quando si utilizza l’iterazione su una mappe, range
restituirà sia il chiave che il valore:
Outputcolor: blue
location: ocean
name: Sammy
animal: shark
Nota:È importante notare che l’ordine in cui una mappa viene restituita è casuale. Ogni volta che eseguite questo programma potete ottenere risultati diversi.
Ora che abbiamo imparato come iterare su dati sequenziali con range
e for
loop, guardate come funzionano le loop nested.
Loop Nested
I cicli possono essere annidati in Go, come avvenga con altre lingue di programmazione. L’annidamento si verifica quando abbiamo un costrutto all’interno di un altro. In questo caso, un ciclo annidato è un ciclo che si verifica all’interno di un altro ciclo. Questi possono essere utili quando si desidera che un’azione ripetuta venga eseguita su ogni elemento di un insieme di dati.
I cicli annidati sono strutturalmente simili agli istruzioni if
annidate. Vengono costruiti così:
for {
[Action]
for {
[Action]
}
}
Il programma prima incontra il ciclo esterno, eseguendo la sua prima iterazione. questa prima iterazione attiva l’interno, il ciclo annidato, che quindi viene eseguito fino a compimento. Poi il programma torna in cima al ciclo esterno, completando la seconda iterazione e attivando di nuovo il ciclo annidato. Di nuovo, il ciclo annidato viene eseguito fino a compimento, e il programma torna in cima al ciclo esterno finché la sequenza non è completa o un break o un’altra istruzione disturbano il processo.
Ora implementeremo un ciclo for
annidato per osservare più da vicino. In questo esempio, il ciclo esterno iterherà attraverso una slice di interi chiamata numList
, e il ciclo interno iterherà attraverso una slice di stringhe chiamata alphaList
.
Quando avremo eseguito questo programma, ricevermo come output il seguente risultato:
Output1
a
b
c
2
a
b
c
3
a
b
c
Il programma completa la prima iterazione dell’albero esterno stampando
Gli for
loop annidati possono essere utili per iterare su elementi costituiti da intervalli composti di intervalli. In un intervallo composto di intervalli, se usiamo solo uno for
loop, il programma stamparà ogni elenco interno come singolo elemento:
Output[0 1 2]
[-1 -2 -3]
[9 8 7]
Per accedere ad ogni singolo elemento dell’interno degli elenchi, implementare un for
loop nested:
Output0
1
2
-1
-2
-3
9
8
7
Quando utilizziamo un for
loop annidato qui, abbiamo la possibilità di iterare sui singoli elementi contenuti nell’intervalli.
Conclusione
Nel presente tutorial abbiamo imparato come dichiarare e usare i for
loop per risolvere le task ripetitive in Go. Abbiamo anche studiato le tre varianti differenti di un for
loop e quando usarle. Per ulteriori informazioni sul funzionamento dei for
loop e sulla gestione del flusso di lavoro nei loro ambiti, leggere Using Break and Continue Statements When Working with Loops in Go.
Source:
https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go