Zgłęb wiedzę na temat pętli `for` w języku Golang, analizując praktyczne przykłady kodu.
W ostatnim czasie, języki programowania takie jak Rust, Golang i TypeScript zdobywają uznanie wśród programistów. Jeśli Twoim obszarem zainteresowań jest tworzenie backendu i DevOps, warto rozważyć Golang jako doskonały wybór!
Dla osób stawiających pierwsze kroki w programowaniu, struktury pętli stanowią jedną z podstawowych koncepcji, które należy opanować.
Golang oferuje wyłącznie pętlę `for`. W dalszej części artykułu szczegółowo omówimy jej działanie oraz sposoby symulowania innych rodzajów pętli za jej pomocą.
Zacznijmy!
Składnia pętli `for` w Golang
W Golang pętlę `for` tworzy się za pomocą następującej konstrukcji:
for inicjalizacja; warunek; aktualizacja {
// kod do wykonania
}
Gdzie:
- `inicjalizacja` – to etap ustalania początkowej wartości zmiennej sterującej pętlą.
- `warunek` – decyduje o tym, czy ciało pętli będzie kontynuowane. Dopóki warunek jest spełniony (ma wartość `true`), instrukcje wewnątrz pętli są wykonywane. W momencie gdy warunek przestaje być prawdziwy (przyjmuje wartość `false`), pętla zostaje zakończona.
- `aktualizacja` – to modyfikacja zmiennej sterującej pętlą, najczęściej poprzez inkrementację (zwiększenie) lub dekrementację (zmniejszenie).
💡 Warto zauważyć, że jest to struktura zbliżona do pętli `for` w języku C, z tą różnicą, że nie używa nawiasów.
Poniżej przedstawiony jest schemat przepływu sterowania w pętli `for` w Golang:
Przejdźmy do praktyki!⏰ Aby móc kodować razem, możesz skorzystać z lokalnej instalacji Golanga lub wykorzystać Go Playground.
Przykłady pętli `for` w Golang
Wykorzystajmy poznaną składnię, aby napisać naszą pierwszą pętlę `for`. Poniżej znajduje się prosta pętla, która wyświetla liczby od 1 do 5, zwiększając licznik o 1 w każdej iteracji.
package main
import "fmt"
func main() {
fmt.Println("Pętla for:")
num := 5
for i := 1; i <= num; i++ {
fmt.Println(i)
}
}
Inicjalizujemy zmienną `i` wartością 1, ustawiamy warunek `i <= 5` i zwiększamy `i` o 1 po każdej iteracji. Oto rezultat:
//Wyjście
Pętla for:
1
2
3
4
5
Stwórzmy kolejną pętlę `for`. Tym razem zaczniemy od 5 i będziemy odliczać w dół do 1. Pętla będzie działać tak długo, jak zmienna sterująca będzie większa lub równa 1. Po każdej iteracji zmniejszymy zmienną `i` o 1.
package main
import "fmt"
func main() {
fmt.Println("Pętla for:")
num := 5
for i := num; i >= 1; i-- {
fmt.Println(i)
}
}
Otrzymujemy oczekiwane wyjście:
//Wyjście
Pętla for:
5
4
3
2
1
Jaki jest zakres zmiennej pętli?
Zasięg zmiennej pętli jest ograniczony do bloku pętli `for` i nie można do niej uzyskać dostępu poza tym blokiem.
Aby to potwierdzić, spróbujmy użyć wartości zmiennej `i` poza pętlą:
package main
import "fmt"
func main() {
fmt.Println("Pętla for:")
num := 5
for i := 1; i <= num; i++ {
fmt.Println(i)
}
fmt.Println(i)
}
Zgodnie z oczekiwaniami, wystąpił błąd, który informuje, że `i` jest niezdefiniowane (ponieważ jego zakres jest ograniczony do pętli `for`):
// Wyjście
./prog.go:11:14: undefined: i
Nieskończona pętla `for` w Golang
Czy w Go możemy tworzyć nieskończone pętle `for`? Oczywiście!
Analizując przepływ sterowania w pętli `for`:
- Ciało pętli jest wykonywane, dopóki warunek jest prawdziwy (`true`).
- Gdy warunek staje się fałszywy (`false`), sterowanie opuszcza pętlę.
- Jeśli zatem warunek nigdy nie staje się fałszywy (lub zawsze jest prawdziwy), uzyskujemy nieskończoną pętlę.
Możemy także użyć pętli `for` bez inicjalizacji, warunku i aktualizacji, nie powodując błędów składniowych. Dzięki temu możemy uzyskać pętlę działającą w nieskończoność, wykorzystując konstrukcję podobną do tej:
package main
import "fmt"
func main() {
for {
fmt.Println("działam...")
}
}
//Wyjście
działam...
działam...
działam...
działam...
działam...
//i tak w nieskończoność!
W poniższym przykładzie ustawiamy zmienną `num` na 5. Warunkiem pętli jest `num > 0`. Oznacza to, że pętla będzie działać dopóki num jest większe od zera.
package main
import "fmt"
func main() {
num := 5
for num > 0 {
fmt.Println(num)
}
}
Ponieważ wartość `num` nigdy się nie zmienia, warunek jest zawsze prawdziwy, a pętla działa bez końca!
//Wyjście
5
5
5
5
5
5
//i tak w nieskończoność!
Golang ma tylko konstrukcję pętli `for`, ale za jej pomocą możemy symulować działanie pętli `while` oraz `do-while`. Zobaczmy, jak to zrobić!
Emulowanie pętli `while` za pomocą pętli `for`
Pętla `while` ma zazwyczaj następującą postać:
// inicjalizacja zmiennej sterującej
while (warunek){
// kod do wykonania
// aktualizacja zmiennej sterującej
}
Wspominaliśmy wcześniej, że utworzyliśmy nieskończoną pętlę `for` bez inicjalizacji, warunku i aktualizacji:
for {
// najprostsza nieskończona pętla
}
Możemy więc zmodyfikować pętlę `for`, tak aby zawierała jedynie warunek, dzięki czemu będzie przypominała pętlę `while`:
//inicjalizacja zmiennej sterującej
for warunek {
// kod do wykonania
// aktualizacja zmiennej sterującej
}
Poniżej znajduje się odpowiednik pętli `while` dla pierwszej pętli `for`, którą napisaliśmy:
package main
import "fmt"
func main() {
fmt.Println("Symulacja pętli while")
num := 5
for num > 0 {
fmt.Println(num)
num--
}
}
//Wyjście
Symulacja pętli while
5
4
3
2
1
Emulowanie pętli `do-while` za pomocą pętli `for`
Jeśli programowałeś w języku takim jak C, wiesz, że pętla `do-while` ma następującą strukturę:
// inicjalizacja zmiennej sterującej
do {
//kod do wykonania
// aktualizacja zmiennej sterującej
} while(warunek);
Podstawową różnicą między pętlami `while` i `do-while` jest to, że `while` sprawdza warunek przed wejściem do pętli, natomiast `do-while` sprawdza warunek po wykonaniu ciała pętli.
W pętli `while`, jeśli warunek jest fałszywy, ciało pętli nigdy nie zostanie wykonane. W pętli `do-while` ciało pętli wykona się przynajmniej raz, nawet jeśli warunek jest od początku fałszywy.
Mając to na uwadze, możemy symulować zachowanie pętli `do-while` poprzez:
- Utworzenie nieskończonej pętli `for`
- Użycie instrukcji warunkowej `if` z odpowiednim warunkiem, aby przerwać pętlę
Załóżmy, że chcemy utworzyć pętlę `do-while`, w której warunkiem wykonania ciała pętli jest `num < 0`. Możemy w takim razie napisać pętlę `for` i wyjść z niej, gdy `num >= 0`.
package main
import "fmt"
func main() {
fmt.Println("Symulacja pętli do-while")
num := 5
for {
fmt.Println("pętla działa...")
if num >= 0 {
break
}
}
}
💡 Zauważ, że warunki wykonania pętli gdy `num < 0` oraz przerwania pętli gdy `num >= 0` są równoważne.
Mimo że warunek `num > 0` jest początkowo fałszywy (num wynosi 5), ciało pętli wykona się raz, naśladując działanie pętli `do-while`.
//Wyjście
Symulacja pętli do-while
pętla działa...
Iteracja po tablicach przy użyciu pętli `for`
Podczas iteracji po tablicach w Golang za pomocą pętli `for` i klauzuli `range`, możemy uzyskać dostęp zarówno do indeksów, jak i elementów tablicy. Działa to podobnie do funkcji `enumerate` w Pythonie.
Tworzymy tablicę `numArray` liczb całkowitych, a następnie iterujemy po niej za pomocą pętli `for`:
package main
import "fmt"
func main() {
fmt.Println("Iteracja po tablicy")
numArray := []int{3, 7, 0, 10, 8, 9}
for idx, num := range numArray {
fmt.Println("Na indeksie", idx, ": ", num)
}
}
Jak widać, możemy jednocześnie uzyskać dostęp do indeksu i elementu na danym indeksie:
//Wyjście
Iteracja po tablicy
Na indeksie 0 : 3
Na indeksie 1 : 7
Na indeksie 2 : 0
Na indeksie 3 : 10
Na indeksie 4 : 8
Na indeksie 5 : 9
Użycie `defer` w pętli `for` w Golang
W Golang słowo kluczowe `defer` służy do opóźnienia wykonania funkcji.
Jest ono często używane do zwalniania zasobów i obsługi błędów, ale warto też zrozumieć, jak używać `defer` wewnątrz pętli `for`. Sprawdźmy, co się stanie, gdy użyjemy `defer` w pętli `for` do opóźnienia wywołań funkcji `Println()`.
package main
import "fmt"
func main() {
fmt.Println("Pętla for:")
num := 5
for i := 1; i <= num; i++ {
defer fmt.Println(i)
}
}
💬 Kiedy wywołanie funkcji jest opóźnione za pomocą `defer`, wywołanie to trafia na stos, a jego wykonanie następuje w kolejności LIFO (ostatnie weszło, pierwsze wyszło). Wywołanie następuje dopiero po zakończeniu działania funkcji, w której użyto `defer`.
Zatem `fmt.Println(5)` zostanie wykonane jako pierwsze, a `fmt.Println(1)` jako ostatnie:
//Wyjście
Pętla for:
5
4
3
2
1
Podsumowanie
Oto podsumowanie najważniejszych informacji, których nauczyłeś się w tym poradniku:
- W Golang pętle `for` tworzy się za pomocą składni: `for inicjalizacja; warunek; aktualizacja { //ciało pętli }`.
- Przepływ sterowania w pętli `for` jest dość prosty: zmienna sterująca jest inicjalizowana tylko raz, warunek decyduje o tym, czy wykonać ciało pętli, a aktualizacja odnosi się do modyfikacji zmiennej sterującej po każdej iteracji.
- Zakres zmiennej pętli jest ograniczony do ciała pętli i nie można do niej uzyskać dostępu poza pętlą.
- Mimo że Golang udostępnia tylko konstrukcję pętli `for`, możemy symulować zachowanie pętli `while` i `do-while` za jej pomocą.
- Pętla `for` znajduje zastosowanie również podczas iteracji po tablicach oraz w połączeniu z opóźnieniem wywołań funkcji (`defer`).
Teraz zapoznaj się z pętlami `for` w Pythonie. Miłej nauki!🎉