Module: Control Flow

For Loops

Go Programming: Control Flow - For Loops

Go only has one looping construct: the for loop. However, it's incredibly versatile and can be used to implement various looping patterns. Let's break down the different ways to use for loops in Go.

1. Basic for Loop (Similar to while in other languages)

This is the most common form, resembling a while loop in languages like C, Java, or Python.

package main

import "fmt"

func main() {
  i := 0
  for i < 5 {
    fmt.Println(i)
    i++ // Increment the counter
  }
}

Explanation:

  • i := 0: Initializes a variable i to 0.
  • for i < 5: This is the condition. The loop continues as long as i is less than 5.
  • fmt.Println(i): The code block to be executed in each iteration.
  • i++: Increments i by 1 after each iteration. Without this, the loop would run infinitely.

Output:

0
1
2
3
4

2. for Loop with Initialization, Condition, and Post Statement

This is the most complete form of the for loop, allowing you to declare, initialize, and update the loop counter all within the for statement.

package main

import "fmt"

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

Explanation:

  • i := 0: Initializes i to 0. This happens only once at the beginning of the loop.
  • i < 5: The condition that must be true for the loop to continue.
  • i++: Executed after each iteration.

Output:

0
1
2
3
4

3. for Loop as an Infinite Loop

If you omit the condition, the loop will run forever (or until explicitly stopped with a break statement).

package main

import "fmt"

func main() {
  i := 0
  for {
    fmt.Println(i)
    i++
    if i > 4 {
      break // Exit the loop when i is greater than 4
    }
  }
}

Explanation:

  • for {}: The empty condition means the loop will run indefinitely.
  • break: The break statement is used to exit the loop when the condition i > 4 is met.

Output:

0
1
2
3
4

4. for...range Loop (Iterating over Collections)

The for...range loop is specifically designed for iterating over elements in collections like arrays, slices, strings, maps, and channels.

a) Iterating over a Slice:

package main

import "fmt"

func main() {
  numbers := []int{10, 20, 30, 40, 50}

  for index, value := range numbers {
    fmt.Printf("Index: %d, Value: %d\n", index, value)
  }
}

Explanation:

  • numbers := []int{10, 20, 30, 40, 50}: Creates a slice of integers.
  • for index, value := range numbers: Iterates over the numbers slice.
    • index: The index of the current element.
    • value: The value of the current element.
  • fmt.Printf(...): Prints the index and value of each element.

Output:

Index: 0, Value: 10
Index: 1, Value: 20
Index: 2, Value: 30
Index: 3, Value: 40
Index: 4, Value: 50

b) Iterating over a String:

package main

import "fmt"

func main() {
  message := "Hello, Go!"

  for index, runeValue := range message {
    fmt.Printf("Index: %d, Rune: %c, Unicode: %U\n", index, runeValue, runeValue)
  }
}

Explanation:

  • message := "Hello, Go!": Creates a string.
  • for index, runeValue := range message: Iterates over the string. Strings in Go are sequences of runes (Unicode code points).
    • index: The index of the rune in the string.
    • runeValue: The rune (Unicode code point) at the current index.

Output:

Index: 0, Rune: H, Unicode: U+0048
Index: 1, Rune: e, Unicode: U+0065
Index: 2, Rune: l, Unicode: U+006c
Index: 3, Rune: l, Unicode: U+006c
Index: 4, Rune: o, Unicode: U+006f
Index: 5, Rune: ,, Unicode: U+002c
Index: 6, Rune:  , Unicode: U+0020
Index: 7, Rune: G, Unicode: U+0047
Index: 8, Rune: o, Unicode: U+006f
Index: 9, Rune: !, Unicode: U+0021

c) Ignoring Index or Value:

You can use the blank identifier _ to discard either the index or the value if you don't need it.

package main

import "fmt"

func main() {
  numbers := []int{10, 20, 30}

  // Iterate only over the values
  for _, value := range numbers {
    fmt.Println(value)
  }

  // Iterate only over the indices
  for index := range numbers {
    fmt.Println(index)
  }
}

break and continue Statements

  • break: Immediately terminates the loop and transfers control to the statement following the loop.
  • continue: Skips the rest of the current iteration and proceeds to the next iteration of the loop.
package main

import "fmt"

func main() {
  for i := 0; i < 10; i++ {
    if i == 3 {
      continue // Skip printing 3
    }
    if i == 7 {
      break // Exit the loop when i is 7
    }
    fmt.Println(i)
  }
}

Output:

0
1
2
4
5
6

Key Takeaways:

  • Go has only one looping construct: for.
  • for loops are highly flexible and can be used to implement while-like loops, infinite loops, and iteration over collections.
  • for...range is the preferred way to iterate over slices, strings, maps, and channels.
  • break and continue provide control over loop execution.
  • The blank identifier _ can be used to discard unwanted values from for...range loops.