Go > Core Go Basics > Control Flow > For loops

For Loop with Range in Go (Iterating over a Slice)

This snippet demonstrates how to use the 'for...range' construct in Go to iterate over a slice, accessing both the index and value of each element.

Code Example

This code defines a slice of integers called 'numbers'. The 'for...range' loop iterates over this slice. In each iteration, 'index' represents the index of the current element, and 'value' represents the value of the element at that index. The code prints both the index and the value for each element in the 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)
    }
}

Concepts Behind the Snippet

The 'for...range' construct simplifies iterating over collections like slices, arrays, maps, and strings. It provides both the index (or key for maps) and the value of each element, making it convenient to access and process the elements within the collection.

Real-Life Use Case

Consider a scenario where you have a list of product names and their corresponding prices stored in a slice. Using 'for...range', you can easily iterate through the slice to display each product's name and price on a website or in a report. You could use the index to pull additional data related to that product from elsewhere.

Best Practices

  • Use the blank identifier (_) when you don't need the index or value: If you only need the value, use for _, value := range collection. If you only need the index, use for index := range collection.
  • Avoid modifying the collection within the loop: Modifying the collection you're iterating over can lead to unexpected behavior. If you need to modify it, consider creating a copy first.

Interview Tip

Understand the differences between a regular 'for' loop and a 'for...range' loop. Be able to explain when to use each one and how they work with different data types (slices, arrays, maps, strings).

When to use them

Use 'for...range' when you need to iterate over a collection and access both the index (or key) and value of each element. It's generally more convenient and readable than using a traditional 'for' loop with an index.

Memory Footprint

The 'for...range' construct typically operates on a copy of the underlying data structure (especially for strings). Be mindful of large data structures, as creating a copy can impact performance. However, for slices, the range loop iterates over the slice header, which is a small, fixed-size structure, so the memory overhead is usually minimal.

Alternatives

While you can use a regular 'for' loop with an index to achieve the same result, 'for...range' is generally preferred for its conciseness and readability when iterating over collections.

Pros

  • Readability: 'for...range' is more readable and easier to understand than a regular 'for' loop with an index.
  • Convenience: It provides both the index (or key) and value of each element, simplifying access.
  • Error prevention: It automatically handles the loop termination, reducing the risk of off-by-one errors.

Cons

  • Potential memory overhead: For large data structures (especially strings), creating a copy can consume significant memory.
  • Not suitable for all scenarios: If you need fine-grained control over the iteration process (e.g., skipping elements based on complex logic), a regular 'for' loop might be more appropriate.

FAQ

  • Can I modify the slice elements within the 'for...range' loop?

    Yes, you can modify the slice elements within the loop using the index. However, remember that the 'value' variable is a copy. To modify the original slice, use the index: numbers[index] = newValue.
  • What happens if I don't need the index?

    You can use the blank identifier (_) to discard the index: for _, value := range numbers { ... }