Go > Core Go Basics > Control Flow > Range loops
Iterating with Range in Go
This example demonstrates how to use the range
keyword to iterate over various data structures in Go, including arrays, slices, strings, and maps. Understanding range
is crucial for efficiently processing collections of data.
Basic Range Loop over a Slice
This code iterates over a slice of integers named numbers
. The range
keyword returns both the index and the value for each element in the slice. The fmt.Printf
function then prints the index and value to the console.
package main
import "fmt"
func main() {
numbers := []int{2, 4, 6, 8, 10}
for index, value := range numbers {
fmt.Printf("Index: %d, Value: %d\n", index, value)
}
}
Omitting the Index or Value
In Go, if you don't need the index or the value, you can omit it using the blank identifier _
. If you only want the index, you can simply assign the range
result to a single variable, which will be the index. This avoids unnecessary variable declarations.
package main
import "fmt"
func main() {
numbers := []int{2, 4, 6, 8, 10}
// Omitting the index using the blank identifier '_'
for _, value := range numbers {
fmt.Printf("Value: %d\n", value)
}
// Omitting the value - only index is used
for index := range numbers {
fmt.Printf("Index: %d\n", index)
}
}
Iterating over a String
When iterating over a string with range
, it iterates over Unicode code points (runes), not bytes. Each iteration provides the starting byte index of the rune and the rune value itself. The %c
format specifier is used to print the rune as a character, and %U
prints the Unicode value.
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)
}
}
Iterating over a Map
When iterating over a map, range
returns the key and the value for each entry. The order of iteration is not guaranteed to be the same each time you run the code. Maps are inherently unordered data structures.
package main
import "fmt"
func main() {
studentAges := map[string]int{
"Alice": 20,
"Bob": 22,
"Charlie": 21,
}
for name, age := range studentAges {
fmt.Printf("Name: %s, Age: %d\n", name, age)
}
}
Concepts behind the snippet
The range
keyword provides a convenient way to iterate over elements in arrays, slices, strings, and maps. It abstracts away the details of manual indexing and provides a clean and readable syntax. It simplifies data structure traversal.
Real-Life Use Case
Imagine you're building a web application that processes user data. You might use a range
loop to iterate over a slice of user objects, perform validation on each user's data, and store the results in a database. Or processing HTTP headers from a request.
Best Practices
range
, as this can lead to unpredictable behavior._
to discard values you don't need, improving code clarity and potentially reducing memory usage.
Interview Tip
Be prepared to explain the behavior of range
with different data types. Understand how it handles strings (runes vs. bytes) and how it iterates over maps (unordered).
When to use them
Use range
loops when you need to iterate over a collection of data and perform some operation on each element. It is preferable to traditional for
loops when you need both the index and the value or when you want a more concise syntax.
Memory footprint
The memory footprint of a range
loop is generally small, especially when working with slices and arrays. However, when iterating over large maps or strings, consider the memory implications of copying the data if you are making modifications within the loop. In most common scenarios, the performance overhead is negligible.
alternatives
Alternatives to range
include traditional for
loops with explicit indexing. For example: for i := 0; i < len(mySlice); i++
. However, range
is often more readable and less error-prone, especially when dealing with complex data structures.
pros
cons
for
loops in certain edge cases (rare).
FAQ
-
What happens if I modify the slice inside a range loop?
Modifying the slice (e.g., appending or deleting elements) during arange
loop can lead to unpredictable behavior, potentially causing the loop to skip elements or enter an infinite loop. It's best to avoid modifying the slice within the loop or to create a copy of the slice before iterating. -
Does the order of iteration matter when ranging over a map?
No, the order of iteration is not guaranteed to be the same each time you run the code when ranging over a map. Maps are inherently unordered data structures.