Go range keyword
In Go, the range keyword is used with a Go for loop to iterate over arrays, slices, strings, maps, and channels. Depending on the value being ranged over, each iteration produces one value or two values.
The general form is for values := range expression. You can use both returned values, use only the first value, or discard an unwanted value with the blank identifier _.
Values returned by Go range
The values produced by range depend on the type of the range expression.
| Range expression | First value | Second value |
|---|---|---|
| Array or slice | Index | Element value |
| String | Byte index | Unicode code point as a rune |
| Map | Key | Value |
| Channel | Received element | None |
The second value is optional. For arrays, slices, strings, and maps, omit it when only the index or key is required. For a channel, each iteration returns only the received element.
Go range syntax for one or two values
// First value only
for first := range collection {
// use first
}
// First and second values
for first, second := range collection {
// use first and second
}
// Ignore the first value
for _, second := range collection {
// use second
}
When neither returned value is needed, use for range collection. This form is useful when an action only needs to run once for every item.
Go range with an array
For an array, range returns the zero-based index first and a copy of the element value second.
Use the array index returned by range
In the following program, only the index returned by range is used. The element is then accessed with evens[index].
example.go
package main
import "fmt"
func main() {
var evens = [5] int {2, 4, 6, 8, 10}
// using index returned from range
for index:= range evens {
fmt.Printf("evens[%d] = %d \n", index, evens[index])
}
}
Output
evens[0] = 2
evens[1] = 4
evens[2] = 6
evens[3] = 8
evens[4] = 10
Use the array index and element value
In this program, both values returned by range are assigned: index receives the position and element receives the value at that position.
example.go
package main
import "fmt"
func main() {
var evens = [5] int {2, 4, 6, 8, 10}
// using index and element returned from range
for index,element:= range evens {
fmt.Printf("evens[%d] = %d \n", index, element)
}
}
Output
evens[0] = 2
evens[1] = 4
evens[2] = 6
evens[3] = 8
evens[4] = 10
Go range with a slice
A slice is ranged over in the same way as an array. The first value is the index and the second is the element value.
package main
import "fmt"
func main() {
languages := []string{"Go", "Java", "Python"}
for index, language := range languages {
fmt.Printf("%d: %s\n", index, language)
}
}
Output
0: Go
1: Java
2: Python
Iterate over slice values without the index
Use _ to discard the index when only the slice element is needed.
for _, language := range languages {
fmt.Println(language)
}
Go range with a string
When ranging over a string, Go decodes the UTF-8 text one Unicode code point at a time. The first value is the byte index where the rune begins, and the second value is the rune itself.
Range over an ASCII string by index
This example uses only the index returned by range. Indexing the string with str[index] returns the byte stored at that position.
example.go
package main
import "fmt"
func main() {
var str = "Golang"
// using index returned from range
for index:= range str {
fmt.Printf("str[%d] = %d \n", index, str[index])
}
}
Output
str[0] = 71
str[1] = 111
str[2] = 108
str[3] = 97
str[4] = 110
str[5] = 103
Because this example contains ASCII characters only, each character occupies one byte. For general Unicode text, byte indexes may increase by more than one.
Get the byte index and rune from a string
This example assigns both the byte index and the rune returned during each iteration.
example.go
package main
import "fmt"
func main() {
var str = "Golang"
// using index and element returned from range
for index,element:= range str {
fmt.Printf("str[%d] = %d \n", index, element)
}
}
Output
str[0] = 71
str[1] = 111
str[2] = 108
str[3] = 97
str[4] = 110
str[5] = 103
Range over Unicode characters correctly
Use the rune value returned by range when the string may contain multibyte UTF-8 characters.
package main
import "fmt"
func main() {
text := "Go✓"
for index, character := range text {
fmt.Printf("byte index %d: %c\n", index, character)
}
}
Output
byte index 0: G
byte index 1: o
byte index 2: ✓
The check mark occupies multiple UTF-8 bytes, but range returns it as one rune.
Go range with a map
For a map, range returns a key first and the corresponding value second. Map iteration order is not specified, so programs should not depend on keys appearing in a fixed order.
Use each map key returned by range
In this example, color receives each map key. The value is then obtained with colorMap[color].
example.go
package main
import "fmt"
func main() {
var colorMap = make(map[string]string)
colorMap["white"] = "#FFFFFF"
colorMap["black"] = "#000000"
colorMap["red"] = "#FF0000"
colorMap["blue"] = "#0000FF"
colorMap["green"] = "#00FF00"
for color := range colorMap {
fmt.Println("Hex value of", color, "is", colorMap[color])
}
}
Possible output
Hex value of white is #FFFFFF
Hex value of black is #000000
Hex value of red is #FF0000
Hex value of blue is #0000FF
Hex value of green is #00FF00
The exact order may differ between runs because map iteration order is unspecified.
Get each map key and value
This example assigns both values returned by range: color receives the key and hex receives its value.
example.go
package main
import "fmt"
func main() {
var colorMap = make(map[string]string)
colorMap["white"] = "#FFFFFF"
colorMap["black"] = "#000000"
colorMap["red"] = "#FF0000"
colorMap["blue"] = "#0000FF"
colorMap["green"] = "#00FF00"
for color, hex := range colorMap {
fmt.Println("Hex value of", color, "is", hex)
}
}
Possible output
Hex value of white is #FFFFFF
Hex value of black is #000000
Hex value of red is #FF0000
Hex value of blue is #0000FF
Hex value of green is #00FF00
Go range with a channel
Ranging over a channel receives values until the channel is closed. A range loop over an open channel waits for the next value, so the sender must eventually close the channel when no more values will be sent.
package main
import "fmt"
func main() {
numbers := make(chan int)
go func() {
numbers <- 10
numbers <- 20
numbers <- 30
close(numbers)
}()
for number := range numbers {
fmt.Println(number)
}
}
Output
10
20
30
Generate a numeric range from 1 to 10 in Go
To iterate from one number to another with explicit start, stop, and step values, use the three-part form of the Go for loop. This is the clearest approach for ranges such as 1 to 10 or increments greater than one.
package main
import "fmt"
func main() {
for number := 1; number <= 10; number++ {
fmt.Println(number)
}
}
Use a custom step in a Go numeric loop
Change the post statement to control the step. The following loop prints the odd numbers from 1 through 9.
for number := 1; number <= 10; number += 2 {
fmt.Println(number)
}
Common Go range mistakes
- Assuming map order is fixed: sort the keys separately when deterministic output is required.
- Treating a string index as a character position: the index returned by
rangeis a byte index. - Using
str[index]for Unicode characters: direct string indexing returns a byte, whilerangereturns decoded runes. - Forgetting to close a channel: a range loop waits until the channel is closed.
- Expecting the ranged element to be a writable reference: the element variable receives a value; use the index to update an array or slice element.
Go range FAQs
What is range in Go?
range is a clause used with a for loop to iterate over arrays, slices, strings, maps, and channels. It produces values appropriate to the type being iterated.
How do I ignore the index in a Go range loop?
Use the blank identifier: for _, value := range items. The underscore discards the index.
Does Go range preserve map insertion order?
No. Map iteration order is unspecified. Collect and sort the keys before iteration when a stable order is required.
Why does range over a Go string return byte indexes?
Go strings contain UTF-8 encoded bytes. The index returned by range identifies the byte position at which each decoded rune begins.
How do I loop from 1 to 10 with a step in Go?
Use a three-part for loop, such as for i := 1; i <= 10; i += 2. Change the initial value, condition, and increment to define the numeric sequence.
Go range editorial QA checklist
- Confirm the return values are described correctly for arrays, slices, strings, maps, and channels.
- Verify that string examples distinguish byte indexes, bytes, and runes.
- Label map output as possible output and do not imply a guaranteed iteration order.
- Ensure channel examples close the channel before the range loop can finish.
- Use a standard three-part
forloop when demonstrating numeric start, end, or step values.
Summary of range loops in Go
Use range with a Go for loop to traverse collections and channels. Arrays and slices return an index and element, strings return a byte index and rune, maps return a key and value, and channels return received elements until closed. In this Go Tutorial, we covered these forms with examples and also showed how to write numeric loops with custom bounds and steps.
TutorialKart.com