The range Keyword
In this page:
for index, value := range collection {
// body
}
for key, value := range mapValue {
// body
}
Ranging Over a Slice
range on a slice or array gives you both the index and the value at each step, letting you avoid manually managing an index variable and bounds checks.
Example: Ranging Over a Slice
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Short declaration: create fruits and infer the type
fruits := []string{"apple", "banana", "cherry"}
// Loop over fruits, getting each index and value
for i, fruit := range fruits {
// Print the values followed by a newline
fmt.Println(i, fruit)
}
}
Login to try C/C++/Java/PHP code in the editor
Ignoring the Index or Value
If you only care about the value and not the index (or vice versa), the blank identifier _ discards the part you don't need, satisfying Go's rule that every declared variable must be used.
Example: Ignoring the Index or Value
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Short declaration: create fruits and infer the type
fruits := []string{"apple", "banana", "cherry"}
// Loop over fruits; the blank identifier _ ignores the index
for _, fruit := range fruits {
// Print the values followed by a newline
fmt.Println("fruit:", fruit)
}
}
Login to try C/C++/Java/PHP code in the editor
Ranging Over a Map
range on a map yields each key-value pair, but the order of iteration is deliberately randomized by the Go runtime every time the program runs, which prevents code from accidentally depending on a specific order.
Example: Ranging Over a Map
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
// Short declaration: create ages and infer the type
ages := map[string]int{"Amit": 30, "Sara": 25}
// Short declaration: create total and infer the type
total := 0
// Loop over ages; the blank identifier _ ignores the index
for _, age := range ages {
total += age
}
// Print the values followed by a newline
fmt.Println("total age:", total)
}
Login to try C/C++/Java/PHP code in the editor
Ranging Over a String
range on a string decodes it as UTF-8, yielding the byte index and the rune (full character) at that position -- correctly handling multi-byte characters, unlike a plain byte-index loop.
Example: Ranging Over a String
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// main is where the program starts running
func main() {
for i, r := range "Go!" {
// Print using a format string
fmt.Printf("%d: %c\n", i, r)
}
}
Login to try C/C++/Java/PHP code in the editor
- Assuming the range loop variable is a fresh variable each iteration in older Go versions -- pre-1.22 it was reused, causing common closure-capture bugs.
- Ignoring the index/key that range provides when only the value is needed, instead of using the blank identifier _ to discard it.
- Modifying a slice's length while ranging over it, which does not change how many iterations the already-started range performs.
- range iterates over arrays, slices, strings, maps, and channels, adapting its output to each type.
- For slices/arrays, range yields index and value; for maps, key and value; for strings, byte index and rune.
- Use the blank identifier _ to ignore a value you don't need from range.
- Since Go 1.22, each range iteration gets its own fresh loop variable, avoiding an old class of closure bugs.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: