Lesson 18 · 18 of 20
Looping with range · Go
Loop over slices, maps and strings in Go with for and range: index and value, keys sorted with sort.Strings, and runes for characters.

range walks through a collection and gives two values on each turn. With a slice they are the index and the value: for i, t := range temps prints each day (i+1, because the index starts at 0) and adds up its temperature. t is a copy: changing it does not change the slice.
With a map, range gives the key and the value, but in a random order that may change from one run to the next. With a single variable, for country := range capitals, you get just the key. The keys are collected, sorted with sort.Strings and then walked with for _, country := range countries; the _ throws away the index.
A Go string is a sequence of bytes in UTF-8, and an accented letter such as á takes two of them. range over a string does not give bytes but runes (rune, a Unicode character), together with the byte position where each one starts: that is why 1:á is followed by 3:l.
So len(city) gives 7 bytes, while len([]rune(city)), which turns the string into a slice of runes, gives the 6 characters of Málaga. %c prints a rune as a character.
Code · main.go
package mainimport ( "fmt" "sort")func main() { // Over a slice: the index and a copy of each value. temps, sum := []float64{18.5, 21, 19.5, 23}, 0.0 for i, t := range temps { fmt.Printf("Day %d: %.1f\n", i+1, t) sum += t } fmt.Printf("Average: %.2f\n", sum/float64(len(temps))) // Over a map: key and value, in random order, so sort the keys. capitals := map[string]string{"Spain": "Madrid", "Italy": "Rome", "France": "Paris"} countries := make([]string, 0, len(capitals)) for country := range capitals { countries = append(countries, country) } sort.Strings(countries) for _, country := range countries { fmt.Println(country, "->", capitals[country]) } // Over a string: the byte position and each rune (character). city := "Málaga" for pos, r := range city { fmt.Printf("%d:%c ", pos, r) } fmt.Println("| bytes:", len(city), "runes:", len([]rune(city)))}Output · go run main.go
Day 1: 18.5 Day 2: 21.0 Day 3: 19.5 Day 4: 23.0 Average: 20.50 France -> Paris Italy -> Rome Spain -> Madrid 0:M 1:á 3:l 4:a 5:g 6:a | bytes: 7 runes: 6
Key points
for i, v := range slicegives index and value.for k, v := range mgives key and value, in random order._drops the index or the key when you do not need it.rangeover a string gives runes, not bytes.len(s)counts bytes;len([]rune(s))counts characters.
Exercise
Use range over the string "Cádiz y León" and count its vowels, with or without an accent, using a switch on each rune.