Learn back-end development by writing real code

Boot.dev Blog ยป Golang ยป For Loops in Go

For Loops in Go

By Lane Wagner on Apr 10, 2021

Last updated on Oct 12, 2022

Curated backend podcasts, videos and articles. All free.

Want to improve your backend development skills? Subscribe to get a copy of The Boot.dev Beat in your inbox each month. It's a newsletter packed with the best content for new backend devs.

For loops are a programmer’s best friend! They allow us execute blocks of code repeatedly and iterate over collections of items. In Go, there are several different ways to write one.

๐Ÿ”— #1 The standard 3-component loop

// prints numbers 0 -> 99
for i := 0; i < 100; i++ {
    fmt.Println(i)
}

The 3 components of a for loop in Go are:

  • The init statement, i := 0
  • The condition, i < 100
  • The post statement, i++

Here’s how the Go compiler executes for-loops:

  1. The init statement declares variables which are then available to the scope of the loop’s body.
  2. The condition is computed. If it evaluates to true then the body runs, otherwise the loop is complete.
  3. The post statement runs.
  4. Back to step #2

Observe: Go’s loop syntax looks similar to that of C, Java, or JavaScript. The biggest difference is the simple lack of parentheses surrounding the components.

๐Ÿ”— #2 For-range loop

I’ve found that I’m rarely using Go’s standard loop syntax, because I’m usually looping over a collection of values. If you need to iterate over a map, slice, channel, or string, Go makes it easy with the range keyword.

๐Ÿ”— Range over a slice in Go

fruits := []string{"apple", "banana", "pear"}
for i, fruit := range fruits {
    fmt.Println(i, s)
}

// prints:
// 0 apple
// 1 banana
// 2 pear

๐Ÿ”— Range over a map in Go

ages := map[string]int{
    "lane":    26,
    "preston": 28,
    "rory":    21,
}
for name, age := range ages {
    fmt.Println(name, age)
}

// prints:
// lane 26
// preston 28
// rory 21

๐Ÿ”— Range over a channel in Go

ch := make(chan int)
go func() {
    for i := 0; i < 3; i++ {
        ch <- i
    }
    close(ch)
}()

// loop ends when channel is close
for value := range ch {
    fmt.Println(value)
}
fmt.Println("channel closed")

// prints:
// 0
// 1
// 2
// channel closed

๐Ÿ”— Range over a string in Go

name := "lane"
for i, char := range name {
     // cast the rune to a string for printing 
     fmt.Println(i, string(char))
}

// prints
// 0 l
// 1 a
// 2 n
// 3 e

๐Ÿ”— #3 While loop in Golang

While loops don’t exist in Go! However, by modifying a for loop we can get the same functionality.

sum := 1
for sum < 10 {
    sum += sum
}
fmt.Println(sum)

In other words, a for loop in Go without an init or post statement is equivalent to a while loop in other languages.

๐Ÿ”— #4 Optional components loop

Building on the idea of a flexible for-loop, we can omit the init or post statements of the three-component loop as we please.

i := 0
for ; sum < 1000; i++ {
    sum += i
}

for i := 0; sum < 1000; {
    sum += i
    i++
}

This can be a useful pattern when you want something like a do-while, or an immediate first tick from a ticker.

๐Ÿ”— #5 Infinite loop

Infinite loops are useful when you have a worker or process that need to run forever, like a web crawler.

sum := 0
for {
    sum++ // repeated forever
}
// never reached, loops continues on forever

๐Ÿ”— #6 Break from a loop

Breaking early from a loop can be useful, especially in an infinite loop. The break keyword will exit the loop immediately.

sum := 0
for {
    sum++
    if sum >= 1000 {
        break
    }
}
fmt.Println(sum)

// prints:
// 1000

๐Ÿ”— #7 Continue (skip to the next iteration) in a loop

It can be useful to skip to the next iteration of a loop early. I do this all the time to create guard clauses within a loop.

for i := 0; i < 10; i++{
    if i % 2 == 0 {
        continue
    }
    fmt.Println(i, "is odd")
}

// prints
// 1 is odd
// 3 is odd
// 5 is odd
// 7 is odd
// 9 is odd

Find a problem with this article?

Report an issue on GitHub