For loop in Golang - A complete guide

Introduction

Golang is an excellent language and the creators of Golang have intelligently implemented for-loop in the language.

Golang is an opinionated language designed to promote simplicity, efficiency, and maintainability in software development through its specific design choices and principles.

This is the reason they have implemented “for-loop” and have ignored loops like “while”, ” do-while”, ”for each” etc.

You can achieve all these loops using only for-loops. You can try running the examples in this blog in the Online Golang playground

Basics of the “for-loop in Golang”

In Golang, a for-loop repeatedly executes a block of code based on a specified condition. The syntax of the Golang for-loop is similar to that of other languages and consists of three main components:

for initialization; condition; post{
       // statements....
}

The initialization statement is optional; it starts its execution before the for-loop begins. It is typically a simple statement, such as a variable declaration, increment or assignment statement, or function call.

The condition statement contains a boolean expression that is evaluated at the beginning of each iteration of the loop. If the condition is true, the loop will keep executing.

Once the loop body completes its execution, the post statement is executed. Subsequently, the condition is re-evaluated. If the condition is true, the loop continues executing all the statements again. However, if the condition evaluates to false, the loop comes to an end.

The following flowchart shows how a Go for-loop works:

Golang For loop Execution Flow Chart

  1. Start: This is where the loop begins.
  2. Initialization Statement: This sets up the loop control variables.
  3. Test Condition: This checks if the loop should keep running. If it's true, the loop body runs; if it's false, the loop ends and moves to the Stop point.
  4. Loop Body: This is the code that runs if the condition is true.
  5. Update: After updating the loop control variables, the process iterates, re-evaluating the condition. If the condition is false, the loop halts.

Golang for-loop as a “While Loop”

If you skip the initialisation and update parts, a for-loop can work like a while loop. In this setup, the loop keeps going as long as the condition remains true, just like a while loop in other languages. 

For condition {   
    // Loop body          
}

In the below example, the counter starts at 0. The loop continues to execute as long as the counter is less than 5. For counter < 5 { this condition is similar to a while loop. Loop will run while the value of the counter is less than 5.

You can check out a complete example at this link 

Golang for loop as a while loop

Golang for-loop as an “Infinite Loop”

In Golang, you can make a for-loop an “Infinite Loop” by skipping the initialisation, condition, and post-statement parts. This loop will continue indefinitely until you explicitly exit it using a break statement or another control method. 

For condition {   
    // Loop body          
}

In the below example, The variable winningNumber is set to 7. This is the number that will cause the loop to exit when it is randomly generated.

A for-loop is an infinite loop that runs indefinitely until a break statement is encountered.

Inside the lo op, a random number between 0 and 9 (inclusive) is generated using rand.Intn(10). if number == winningNumber condition checks if the generated number is equal to the winningNumber (which is 7).

If the condition is true, the message “You won the lottery! Exiting the loop…” is printed, and the break statement is executed to exit the loop.

Once the loop is exited, the line “Loop exited” gets printed. Enjoy your winnings!” to the console. This indicates the end of the program and celebrates the user’s “win.”

You can check out a complete example at this link 

Golang for loop as infinite loop

Golang for-loop as a “Do While Loop”

Golang does not have a do-while loop like other languages. You can simulate the behaviour of a do-while loop using a for-loop. In a do-while loop, the loop body executes at least once, followed by continued execution as long as a specified condition remains true

Golang for loop as do while loop

We can refer to the same example as explained in the infinite loop. The for-loop structure ensures that the loop body executes at least once, similar to a do-while loop. 

Nested for-loops

Nested for-loops refers to loops within other loops. They are commonly used to iterate over multidimensional data structures. Below is an example demonstrating a nested loop. 

   size := 5
   // Outer loop for the rows
   for row := 1; row &lt;= size; row++ {
       // Inner loop for the columns
       for column := 1; column &lt;= size; column++ {
           fmt.Printf(&quot;%4d&quot;, row*column) // Print the product of i and j
       }
       fmt.Println() // Move to the next line after each row
   }

Following loop is the outer loop that iterates over the rows. 

for row := 1; row &lt;= size; row++ {

Following loop is the inner loop that iterates over the columns

for column := 1; column &lt;= size; column++ {

Inside the inner loop, this line prints the product of i and j.

fmt.Printf("%4d", row*column)

Output

   1   2   3   4   5
   2   4   6   8  10
   3   6   9  12  15
   4   8  12  16  20
   5  10  15  20  25

You can check out a complete example at this link 

For loop over Channel

You can use a golang for-loop with a channel to send and receive data until the channel is closed. The following example illustrates sending values to a Go channel and reading those values in a Goroutine using another loop. 

func main() {
	//send values to ch1 in the loop and read values in goroutine 1 in the loop
	ch1 := make(chan int)
	go channelValueReader(ch1)

	for counter := 1; counter &lt;= 5; counter++ {
		ch1 &lt;- counter
	}
}

func channelValueReader(ch chan int) {
	for channelValue := range ch {
		fmt.Println('Current value in channel is: ", channelValue)
	}
}

In the above example, the following line of code sends the value of the counter to the ch1 channel using the <- operator. 

for counter := 1; counter &lt;= 5; counter++ {
    ch1 &lt;- counter
}

The function called channelValueReader takes a channel that contains integers as input. Inside this function, there’s a for-loop that keeps reading values from the channel using the range keyword. It continues reading values until the channel is closed. Each time it gets a value, it prints out “Current value in the channel is: ” followed by the value itself. 

func channelValueReader(ch chan int) {
   for channelValue := range ch {
       fmt.Println("Current value in the channel is: ", channelValue)
   }
}

You can check out a complete example at this link 

For loop with range keyword / Foreach loop

Range is used to iterate over various data structures like slices, maps, arrays, and channels. It returns two values: the first is the index as an integer value, and the second is the value copy of the element at that index. The range keyword in Go functions similarly to a “for each” loop found in other programming languages. Following is the basic syntax for range. 

for index, value := range datastructure {
        fmt.Println(value)
}

Blank identifier

A blank identifier is used to ignore the returned values that you don’t need. You can ignore the index, ignore the value, or ignore both. 

Index as a blank identifier

In the following example, the for-loop iterates over each element of the colour slice. It uses the range keyword to get both the index and value of each element. However, the index is assigned to the blank identifier _, indicating that we want to ignore it. 

colors := []string{"blue", "green", "red", "white"}
// Iterate over each element in the colors slice, ignoring the index
for _, value := range colors {
	fmt.Println("Color is :", value)
}

Value as a blank identifier

In the following example, the for-loop iterates over each element of the colour slice. The index of each element is assigned to the variable index, while the value of each element is assigned to a blank identifier, indicating that we want to ignore it. Even if you don’t mention “_” here, it will also give a return value as an index. 

colors := []string{"blue", "green", "red", "white"}

// Iterate over each element in the colours slice, ignoring the value
for index, _ := range colors {
    fmt.Println("Colour index is:", index)
}

Avoid using both index and value in the iteration

In the following example The for-loop iterates over each element of the color slice. Here both the index and value are ignored. 

colors := []string{"blue", "green", "red", "white"}

// Iterate over each element in the colours slice, ignoring both index and value
for range colors {
    fmt.Println("Same colour!")
}

Looping over array and slices using range for-loop

It returns the first value as the index of the current element, and the second value is the value of the current element. You can check out a complete example at this link  

Golang looping over arrays slices using range for loop

Looping over maps using range for-loop

The first value that is returned by the map is the key, and the second value returns the value from the key-value pair. You can check out a complete example at this link  

Golang loop over maps using range for loop

Looping over strings using range for-loop

Using range on the string, it returns the first value as index, and the second value is rune(int32). You can check out a complete example at this link  

Golang looping over string using range for loop

Looping over integer using range for-loop

In Go version 1.22, a new feature has been introduced that allows you to use the for-loop with the range keyword to iterate over integers. You can find more information about this feature in the Go 1.22 release notes on the official Go blog 

for i := range 10 {
    fmt.Println(10 - i)
}
fmt.Println("go1.22 has lift-off!")

Loop Control Statements

"Break" Loop Control Statement

The “break” statement stops the loop before it would normally end based on its condition. 

Golang break loop control statement

In this example, the loop iterates through a list of signals. If the signal is red, it breaks the loop and prints the signal and its index. You can check out a complete example at this link 

"Continue" Loop Control Statement

It skips the current iteration of the loop and proceeds with the next iteration. 

Golang continue loop control statement

In the above example, the loop iterates through a list of signals. If the signal is green, it continues to the next iteration, printing that it is continuing at the green signal. If the signal is not green, it prints that it is stopping at the signal and exits the loop. You can check out a complete example at this link

"Goto" Loop Control Statement

It starts jumping to a labelled statement elsewhere in the code.. You can check out a complete example at this link

Golang goto loop control statement

“for-loop” vs “for-loop with range”

for-loop
for-loop with range
Iterate over a range of values
Iterate over various data structures like slices, maps, arrays, channels
Requires explicit error handling if applicable.
Automatically handles iteration and, in certain cases, simplifies error handling with built-in mechanisms.

Time complexity

Determine by the number of iterations and the operations within the loop. Hence, for basic loops, it is O(n), and for nested loops, it is O(n*m), where n represents the number of iterations for the outer loop and m represents the number of iterations for the inner loop. 

Best Practices

  • Use clear and descriptive names for your variables so others can easily understand your code.
  • Keep the processing inside loops to a minimum to make your code faster and easier to understand.
  • Choose the right data structures for your needs to make your code run efficiently.
  • Avoid using nested loops when you can to make your code simpler and faster.