4 ways to write a range for loop [slice, string, map, channel]


Basic for-each loop (slice or array)

a := []string{"Foo", "Bar"}
for i, s := range a {
    fmt.Println(i, s)
0 Foo
1 Bar

String iteration: runes or bytes

For strings, the range loop iterates over Unicode code points.

for i, ch := range "日本語" {
    fmt.Printf("%#U starts at byte position %d\n", ch, i)
U+65E5 '日' starts at byte position 0
U+672C '本' starts at byte position 3
U+8A9E '語' starts at byte position 6
To loop over individual bytes, simply use a normal for loop and string indexing:
const s = "日本語"
for i := 0; i < len(s); i++ {
    fmt.Printf("%x ", s[i])
e6 97 a5 e6 9c ac e8 aa 9e

Map iteration: keys and values

The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next.

m := map[string]int{
    "one":   1,
    "two":   2,
    "three": 3,
for k, v := range m {
    fmt.Println(k, v)
two 2
three 3
one 1

Channel iteration

For channels, the iteration values are the successive values sent on the channel until closed.

ch := make(chan int)
go func() {
    ch <- 1
    ch <- 2
    ch <- 3
for n := range ch {


Here are two traps that you want to avoid when using range loops:

Share this page: