Hoe bouw je for-loops in Go

Inleiding

In computersprogrammeren is een loop een code-structuur die zich herhaalt om een stukje code telkens opnieuw uit te voeren, vaak totdat een bepaalde conditie is waar. Door gebruik te maken van loops in computersprogrammeren kunt u taken automatiseren en meerdere malen herhalen. Denk erbij hoeveel werk het zou zijn om een lijst met bestanden te verwerken of hoeveel regels er zijn in een artikel. U zou een loop in uw code gebruiken om dergelijke problemen op te lossen.

In Go implementeert een for-loop de herhalde uitvoering van code op basis van een loop teller of loop variabele. In tegenstelling tot andere programmeertalen die meerdere looptconstructies zoals while, do enzovoort hebben, heeft Go alleen de for-loop. Dit dient om uw code helderder en leesbaarder te maken, omdat u niet hoeft te worstelen met meerdere strategieën om hetzelfde looptconstructie te bereiken. Deze verbetering van leesbaarheid en de verminderde cognitieve belasting tijdens ontwikkeling zal ook uw code minder gevoelig voor fouten maken dan in andere talen.

In deze handleiding zult u leren hoe Go’s for-loop werkt, inclusief de drie grote varianten van zijn gebruik. We zullen beginnen door verschillende typen for-loops te tonen, gevolgd door hoe u door sequentiële data types in Go kunt loopen. We zullen eindigen door teexplainen hoe u nested loops kunt gebruiken.

Declaratie voor clausules en conditie loops

Om een aantal gebruiksgevalen te kunnen accounteren, zijn er drie verschillende manieren om een for-loop te maken in Go, elk met hun eigen capaciteiten. Deze zijn de variant met een Condition, de variant met een ForClause, of de variant met een RangeClause. In deze sectie zullen we uitleg geven over hoe je de ForClause en de Condition variant kan declareren en gebruiken.

Laten we eerst kijken hoe we een for-loop kunnen declareren met de ForClause.

Een ForClause loop wordt gedefineerd als een combinatie van een initial statement, gevolgd door een conditie, en dan een post statement. Dit wordt op de volgende syntaxis geordend:

for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
    [Action]
}

Om te verduidelijken wat de onderdelen hiervan doen, lees je hieronder een for-loop die door een specifieke reeks waarden wordt geïncrèmeerd met behulp van de ForClause syntaxis:

for i := 0; i < 5; i++ {
	fmt.Println(i)
}

Kom je dit loop tegen, dan breek je hem af en identificeer je elk onderdeel.

Het eerste onderdeel van de loop is i := 0. Dit is de initial statement:

for i := 0; i < 5; i++ {
	fmt.Println(i)
}

Het stelt dat je een variabele i declareert en haar initiale waarde instelt op 0.

Volgens de conditie:

for i := 0; i < 5; i++ {
	fmt.Println(i)
}

In deze conditie zegt hij dat terwijl i minder is dan de waarde van 5, moet de loop blijven lopen.

Ultimately, we have the post statement:

for i := 0; i < 5; i++ {
	fmt.Println(i)
}

In de for-lus stelten we de loop variabele i telkens op bij een iteratie met behulp van de i++ opwaardeer operator.

Wanneer we deze programma uitvoeren, zien we het volgende resultaat:

Output
0 1 2 3 4

De loop heeft 5 keer ge运行d. Eenmaal startte hij i aan met 0, en dan checkte hij of i minder was dan 5. Zoals de waarde van i minder was dan 5, werd de actie van fmt.Println(i) uitgevoerd. Na de loop te zijn afgerond, werd de poststatement van i++ gebruikt en de waarde van i werd verhoogd met 1.

Gezien: Bekijk dat in programmeren we vaak beginnen bij index 0, dus is het dat alleen maar 5 nummers worden geprinted, maar van 0-4.

We zijn niet beperkt tot beginnen bij 0 of eindigen bij een specifieke waarde. We kunnen elke gewenste waarde aan onze initiële declaratie toevoegen, en ook stoppen bij elke gewenste waarde in onze poststatement. Dit geeft ons de mogelijkheid om elke gewenste reeks te doorloopen:

for i := 20; i < 25; i++ {
	fmt.Println(i)
}

Hier gebruiken we onze poststatement met een positieve waarde:

Output
20 21 22 23 24

In dit geval is de iteratie ingesteld vanaf 20 (inclusief) tot 25 (exclusief), dus het resultaat ziet er als volgend uit:

We kunnen ook onze poststatement gebruiken met een positieve waarde voor de step in andere talen:

for i := 0; i < 15; i += 3 {
	fmt.Println(i)
}

Eerst stellen we de iteratie aan met een positieve waarde:In deze situatie worden de cijfers van 0 tot 15 geprinted, maar met een stap van 3, zodat alleen elke derde cijfer wordt geprinted, zoals hieronder:

Output
0 3 6 9 12

We kunnen ook een negatieve waarde gebruiken voor onze poststatementargument om terug te iteratieren, maar we moeten onze initiële statement en conditie argumenten corresponderen:

for i := 100; i > 0; i -= 10 {
	fmt.Println(i)
}

Hier stellen we i aan met een initiele waarde van 100, gebruik de conditie van i < 0 om te stoppen bij 0, en de post statement vermindert de waarde met de operator -= door 10. De loop begint bij 100 en eindigt bij 0, met elke iteratie afnemen van 10. We kunnen dit zien in de uitvoer:

Output
100 90 80 70 60 50 40 30 20 10

Je kunt ook de initiële statement en de post statement uit de for syntaxon negeren, en alleen de conditie gebruiken. Dit wordt bekend als een Condition loop:

i := 0
for i < 5 {
	fmt.Println(i)
	i++
}

Dit keer declareer je de variabele i apart van de for loop in de vorige lijn van code. De loop heeft slechts een conditie clausule die checkt of i minder is dan 5. Zolang de conditie evalueert naar true blijft de loop iteratief.

Soms zou je niet weten hoe vaak je een bepaalde taak moet uitvoeren. In dat geval kan je alle statements omissen en gebruik je de break keyword om executie te stoppen:

for {
	if someCondition {
break
}
	// do action here
}

Een voorbeeld hiervan is wanneer je vanuit een onbekende grootte structuur leest, zoals een buffer en je niet weet wanneer je klaar bent met lezen:

buffer.go
package main

import (
	"bytes"
	"fmt"
	"io"
)

func main() {
	buf := bytes.NewBufferString("one\ntwo\nthree\nfour\n")

	for {
		line, err := buf.ReadString('\n')
		if err != nil {
			if err == io.EOF {

				fmt.Print(line)
				break
			}
			fmt.Println(err)
			break
		}
		fmt.Print(line)
	}
}

>buf :=bytes.NewBufferString(“one\ntwo\nthree\nfour\n”) declareert een buffer met enige gegevens. Omdat we niet weten wanneer de buffer zal stoppen met lezen, maken we een for-lus zonder clausule. Binnenin de for-lus gebruiken we line, err := buf.ReadString('\n') om een regel van de buffer te lezen en te controleren of er een fout is opgetreden bij het lezen van de buffer. Als dat zo is, lossen we de fout op en gebruiken we het sleutelwoord break om de for-lus te verlaten. Met deze break-punten hoeven we geen voorwaarde opnemen om de lus te stoppen.

In dit gedeelte hebben we geleerd hoe een ForClause-lus te declareren en deze te gebruiken om door een bekend bereik van waarden te itereren. We hebben ook geleerd hoe een Condition-lus te gebruiken om te itereren totdat een specifieke voorwaarde is vervuld. Vervolgens zullen we leren hoe de RangeClause wordt gebruikt voor het itereren door sequentiële gegevenstypen.

Door sequentiële gegevenstypen itereren met RangeClause

In Go is het gebruikelijk for-lussen te gebruiken om over de elementen van sequentiële of collectie gegevenstypen zoals slices, arrays en strings heen te itereren. Om dit gemakkelijker te kunnen doen, kunnen we een for-lus gebruiken met de RangeClause-syntax. Terwijl u door sequentiële gegevens typen kunt itereren met de ForClause-syntax, is de RangeClause netter en gemakkelijker te lezen.

Voordat we kijken hoe we de RangeClause kunnen gebruiken, laten we kijken hoe we door een slice kunnen itereren met behulp van de ForClause-syntax:

main.go
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])
	}
}

Als u dit uitvoert, krijgt u het volgende resultaat, dat elk element van de slice afdrukt:

Output
hammerhead great white dogfish frilled bullhead requiem

Nu gaat u dezelfde actie uitvoeren met de RangeClause:

main.go
package main

import "fmt"

func main() {
	sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

	for i, shark := range sharks {
		fmt.Println(i, shark)
	}
}

In dit geval print u elk item in de lijst uit. Hoewel we de variabelen i en shark gebruikt hebben, hadden we de variabele kunnen noemen als elke andere geldige variabelenaam en zou hetzelfde resultaat zijn:

Output
0 hammerhead 1 great white 2 dogfish 3 frilled 4 bullhead 5 requiem

Bij het gebruik van range op een slice, wordt altijd twee waarden teruggegeven. Het eerste waar is de index die de huidige iteratie van de lus in zit, en het tweede is de waarde op die index. In dit geval was de index voor de eerste iteratie 0, en de waarde was hammerhead.

Soms wil je alleen de waarde binnenin de slicetijden uitprinten, niet de index. Als je de vorige code aanpast om alleen de waarde te printen, krijg je een compile-fout:

main.go
package main

import "fmt"

func main() {
	sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

	for i, shark := range sharks {
		fmt.Println(shark)
	}
}
Output
src/range-error.go:8:6: i declared and not used

Omdat i is gedeclareerd binnen de for lus, maar nooit gebruikt wordt, reageert de compiler met de fout van i gedeclared en niet gebruikt. Dit is hetzelfde fout dat je in Go krijgt als je een variabele declareert en er geen gebruik van maakt.

Door deze reden heeft Go de blank identificator welke een onderstreping (_) is. Binnen een for lus, kunt u de blanco identificator gebruiken om elk argument terug te krijgen van de range keyword. In dit geval wilt u de index overschrijven, die de eerste argument terugbrengt.

main.go
package main

import "fmt"

func main() {
	sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

	for _, shark := range sharks {
		fmt.Println(shark)
	}
}
Output
hammerhead great white dogfish frilled bullhead requiem

Dit resultaat laat zien dat de for lus door de lijst van strings heeft geiterd en elk item van de lijst uitgeprint heeft zonder de index.

U kunt ook range gebruiken om items toe te voegen aan een lijst:

main.go
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']

Hier hebben we een plaatshalvering van de string "shark" toegevoegd aan elk item van de lengte van de sharks slice.

Zie hetzelfde, we hoeven de declaratie deel van de range oproep niet te gebruiken als we geen van de terugbrengingen van de range operator nodig zijn. Go stelt ons toe om de hele declaratie deel van de range oproep te laten blijven leeg indien we geen van de terugbrengingen gebruiken.

We kunnen ook range gebruiken om waarden te vullen van een slice:

main.go
package main

import "fmt"

func main() {
	integers := make([]int, 10)
	fmt.Println(integers)

	for i := range integers {
		integers[i] = i
	}

	fmt.Println(integers)
}

In deze voorbeeldcode wordt de slicet integers initialiseerd met tien lege waarden, maar de for-loop stelt alle waarden in de lijst als volgens:

Output
[0 0 0 0 0 0 0 0 0 0] [0 1 2 3 4 5 6 7 8 9]

De eerste keer we de waarde van de slicet integers printen, zien we alle zeros. Dan iteratie je door elke index en stel de waarde bij de huidige index. Daarna print je de waarde van integers een tweede keer, zodat ze allemaal een waarde hebben van 0 tot en met 9.

We kunnen ook de range operator gebruiken om door elk karakter in een tekenreeks te iteratief

main.go
package main

import "fmt"

func main() {
	sammy := "Sammy"

	for _, letter := range sammy {
		fmt.Printf("%c\n", letter)
	}
}
Output
S a m m y

Wanneer je iteratief door een map gaat, geeft range zowel de key als de value terug:

main.go
package main

import "fmt"

func main() {
	sammyShark := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

	for key, value := range sammyShark {
		fmt.Println(key + ": " + value)
	}
}
Output
color: blue location: ocean name: Sammy animal: shark

Opmerking: Het is belangrijk te noteren dat de volgorde waarin een map terugbrengt random is. Elke keer je deze programma uitvoert, krijg je een andere resultaat.

Nu we het gebruik van range en for-loops bij sequentieel data kennen, laten we kijken naar hoe je loopt kan gebruiken binnen loopt.

Gebouwd op niveau

Lussen kunnen in Go worden ingebed, net als in andere programmeer talen. Inbedden is wanneer we een eenvoudige construct binnen een ander construct plaatsen. In dit geval gaat het om een ingebedde lus, een lus die binnen een andere lus plaatsvindt. Dit kan handig zijn als u op elk element van een gegevensset een herhalde actie wilt uitvoeren.

Ingebedde lussen zijn structuurlijk verwant aan ingebedde if-bepalingen. Ze zijn zo geconstrueerd:

for {
    [Action]
    for {
        [Action]  
    }
}

Het programma ondergaat eerst de buitenste lus, en voert zijn eerste iteratie uit. Deze eerste iteratie activeert de binnenste, ingebedde lus, die vervolgens tot afloop loopt. Dan keert het programma terug naar de bovenkant van de buitenste lus, voltooit de tweede iteratie en activeert opnieuw de ingebedde lus. Opnieuw loopt de ingebedde lus tot afloop, en dan keert het programma terug naar de bovenkant van de buitenste lus, tot de reeks voltooid is of een break-instructie of andere bepaling de processus verstoring aanricht.

Laten we een ingebedde for-lus implementeren zodat we hem op een klein scherm kunnen bekijken. In dit voorbeeld zal de buitenste lus door een slice van gehele getallen genaamd numList itereren, en de binnenste lus door een slice van strings genaamd alphaList itereren.

main.go
package main

import "fmt"

func main() {
	numList := []int{1, 2, 3}
	alphaList := []string{"a", "b", "c"}

	for _, i := range numList {
		fmt.Println(i)
		for _, letter := range alphaList {
			fmt.Println(letter)
		}
	}
}

Als we dit programma uitvoeren, krijgen we de volgende uitvoer:

Output
1 a b c 2 a b c 3 a b c

Deze uitvoer illustreert dat de programma de eerste iteratie van de buitenloop voltooid heeft door te printen 1, wat daarop volgt is de volgende iteratie van de binnenloop, waarbij a, b, c sequentieel worden geprinted. Na de voltooien van de binnenloop gaat de programma terug naar de beginnen van de buitenloop, printt 2, en dan opnieuw de binnenloop in zijn geheel (a, b, c), etc.

Gebruik van nested for-loops kan nuttig zijn voor het iteratief doorlopen van items die zijn samengesteld van slices. Bij een slicet met slices kunnen we slechts één for-loop gebruiken; in dat geval zal de programma elke interne lijst als een item printen:

main.go
package main

import "fmt"

func main() {
	ints := [][]int{
		[]int{0, 1, 2},
		[]int{-1, -2, -3},
		[]int{9, 8, 7},
	}

	for _, i := range ints {
		fmt.Println(i)
	}
}
Output
[0 1 2] [-1 -2 -3] [9 8 7]

Om elk individueel item te accessen van de interne slices moeten we een nested for-loop implementeren:

main.go
package main

import "fmt"

func main() {
	ints := [][]int{
		[]int{0, 1, 2},
		[]int{-1, -2, -3},
		[]int{9, 8, 7},
	}

	for _, i := range ints {
		for _, j := range i {
			fmt.Println(j)
		}
	}
}
Output
0 1 2 -1 -2 -3 9 8 7

Wanneer we hier een nested for-loop gebruiken, kunnen we alle individuele items aanhalen die zijn ingebouwd in de slices.

Conclusie

In deze handleiding hebben we leren hoe je for-loops declareert en gebruikt in Go om repetitieve taken te oplossen. We hebben ook de drie verschillende varianten van een for-loop onderzocht en weten wanneer ze gebruikt worden. Voor meer informatie over for-loops en hoe je de flow van ze controleert, lees 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