Start learning free

LESSON 106 OF 338 · FOR LOOPS - LOOPING OVER ARRAYS

Looping Through Arrays in Go: for and range

Lesson Read the full explanation

A for loop is a special type of loop in Go which allows us to loop over the items of a collection, such as a string or an array.


Looping through a string:

For example, a string is a sequence of characters, so we can use a for loop to iterate over each character and do something with that character:

name := "Andy"

for _, letter := range name {
  fmt.Println(string(letter))
}

Let's break down this code:

  • The for keyword that indicates the start of a for loop.
  • _, letter is the loop variable. It will take the value of each different item in the collection
  • The range keyword iterates over the collection we will iterate on
  • name is the collection to loop over

The output of this code is:

A
n
d
y

As you can see, on each iteration, letter was assigned the value of the next item in the string and inside the loop, we printed that value.


Looping through an array:

We can also use for loops with lists:

fruits := []string{"banana", "orange", "pear", "kivi"}

for _, fruit := range fruits {
  fmt.Println("I eat " + fruit)
}

The output of this code is:

I eat banana
I eat orange
I eat pear
I eat kivi

Assignment
Now let's greet our friends using a for loop!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    GO · FOR LOOPS - LOOPING OVER ARRAYS

    Looping Through Arrays in Go, explained

    The for loop and range

    Go has exactly one loop keyword, for. To visit every element of a slice, an array, a string or a map, you combine it with range:

    fruits := []string{"banana", "orange", "pear", "kiwi"}
    
    for _, fruit := range fruits {
        fmt.Println("I eat " + fruit)
    }
    

    Each part has a job:

    • for starts the loop.
    • range fruits says which collection to walk through, from the first element to the last.
    • _, fruit are the two loop variables. On every pass, the first holds the index and the second holds the element at that index.
    • The braces hold the body, which runs once per element.

    The output is:

    I eat banana
    I eat orange
    I eat pear
    I eat kiwi
    

    Why the underscore

    range always offers both the index and the value. Go does not allow a declared variable to go unused, so a loop variable you ignore must be replaced by the blank identifier _. That is why the loops here start with _,. If you want only the index, you can leave the second variable out:

    for i := range fruits {
        fmt.Println(i) // 0, 1, 2, 3
    }
    

    If you want both, name both: for i, fruit := range fruits.

    Looping through a string

    A string can be ranged over too. Each pass gives the byte position of a character and the character itself, as a rune, which is an integer holding a Unicode code point:

    name := "Andy"
    
    for _, letter := range name {
        fmt.Println(string(letter))
    }
    

    This prints A, n, d and y on separate lines. The conversion string(letter) turns the rune back into a one-character string. Without it, fmt.Println(letter) would print the number 65 for A. Indexing a string with name[0] is different: it gives a single byte, not a character. With range, characters outside ASCII still come out whole. Ranging over "héy" would yield three runes, even though the string is four bytes long.

    The index-based alternative

    Go also has the three-part loop, which counts with an index you manage yourself:

    for i := 0; i < len(fruits); i++ {
        fmt.Println(fruits[i])
    }
    

    It prints the same fruits, but it gives you more places to slip: start at the wrong number, use <= instead of < and read one element past the end, which panics. When you only need the elements, range is shorter and safer, so it is the usual choice.

    The exercise, step by step

    The editor starts with a slice named friends holding Andy, Mary and John. The goal is to greet each one.

    1. Write the loop header. Use for _, friend := range friends. The variable is named friend, and the index goes to _ because the greeting doesn't need it.
    2. Print the greeting in the body. Build the text with "Hey, " + friend + "!" and pass it to fmt.Println, which adds the line break. The body runs once per friend, so each name gets its own line.

    The solution in Go

    friends := []string{"Andy", "Mary", "John"}
    
    for _, friend := range friends {
        fmt.Println("Hey, " + friend + "!")
    }
    

    The output is:

    Hey, Andy!
    Hey, Mary!
    Hey, John!
    

    The loop variable friend is a copy of the element for that pass. Changing it inside the body does not change the slice. An empty slice runs the body zero times and prints nothing.

    A slice that is empty or nil is fine too. The loop checks for elements before each pass and simply never enters the body, so no special case is needed in your code.

    Common mistakes

    • Forgetting the underscore. for i, friend := range friends with i never used fails with i declared and not used.
    • Putting the variable in quotes. "Hey, friend!" prints the word friend every time. Join the variable to the text with +.
    • Printing outside the braces. A statement after the closing brace runs once, after the loop, and cannot see the loop variable.
    • Mixing up the order. The index always comes first and the value second.

    Key takeaways

    • for index, value := range collection visits every element in order.
    • Use _ for a loop variable you don't need, since unused variables are compile errors.
    • Ranging over a string gives runes, which you can turn back into text with string(r).
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free