Why loop with indices
Go gives you two ways to walk through a slice. A for ... range loop hands you each element. A counting loop hands you each index, and you read the element yourself with nums[i]. The index form is the one to reach for when the position matters: when you need to print it, return it, change the element in place, or look at a neighbour such as nums[i+1].
The valid indices of a slice meals are the integers from 0 to len(meals) - 1. The built-in len returns the number of elements, and indexing starts at 0, so the last element sits at len(meals) - 1.
The three-part for loop
Go has only one loop keyword, for, and its classic form has three parts separated by semicolons: a starting statement, a condition checked before every pass, and a statement that runs after every pass.
meals := []string{"pancakes", "pasta", "pizza", "avocado"}
for i := 0; i < len(meals); i++ {
fmt.Printf("Meal number %d is %s.\n", i+1, meals[i])
}
This prints:
Meal number 1 is pancakes.
Meal number 2 is pasta.
Meal number 3 is pizza.
Meal number 4 is avocado.
Reading the header piece by piece:
i := 0declares the index, which exists only inside the loop, and starts it at the first position.i < len(meals)keeps the loop going whileiis a valid index. The condition uses<and not<=, becauselen(meals)itself is one past the last element.i++moves to the next position after each pass.
There are no parentheses around the header and the braces are required. Go also has no while keyword: this form, or a for with only a condition, covers every case.
Counting from 1 for display
People count meals from 1, while indices start at 0. The example prints i+1 for the meal number and meals[i] for the element. Keep the two roles separate: i is the position in the slice, and i+1 is only a label.
Other directions and ranges
The three parts can be changed to fit the task. This loop walks backwards, from the last index to 0:
nums := []int{4, 8, 15}
for i := len(nums) - 1; i >= 0; i-- {
fmt.Println(i, nums[i])
}
It prints 2 15, then 1 8, then 0 4. To compare each element with the next one, stop one index early so that i+1 stays valid:
for i := 0; i < len(nums)-1; i++ {
fmt.Println(nums[i], "then", nums[i+1])
}
This prints 4 then 8 and 8 then 15.
Common mistakes
- Using
<=withlen. The loopfor i := 0; i <= len(nums); i++reachesi == 3for a three-element slice. Go checks indices at run time, so the program prints the three elements and then stops withpanic: runtime error: index out of range [3] with length 3. - Printing a number with
+. Go does not join anintto a string with+:"day " + idoes not compile. Convert the number first withstrconv.Itoa(i), or usefmt.Printfwith%d. - Forgetting that the day is
i+1. Printingidirectly starts the numbering at 0.
The exercise
The slice temperatures holds 10, 60, -5, 32. The task is to print one line per day in the form On day 1 the temperature is 10., with the day counted from 1.
- Write the loop. Declare the index
iwith:=, start it at 0, continue while it is less thanlen(temperatures), and increment it after each pass. - Build the text. The line has a day number and a temperature, both integers. Each is converted with
strconv.Itoaand joined to the surrounding text with+. The day isi+1and the temperature istemperatures[i]. - Print it with
fmt.Println.
temperatures := []int{10, 60, -5, 32}
for i := 0; i < len(temperatures); i++ {
fmt.Println("On day " + strconv.Itoa(i+1) + " the temperature is " + strconv.Itoa(temperatures[i]) + ".")
}
The output is:
On day 1 the temperature is 10.
On day 2 the temperature is 60.
On day 3 the temperature is -5.
On day 4 the temperature is 32.
The code uses the fmt and strconv packages, so both are imported in a full program. The negative temperature needs no special care: strconv.Itoa(-5) gives "-5".
Key takeaways
- The valid indices of a slice run from
0tolen(s) - 1. - The loop
for i := 0; i < len(s); i++visits each index once. Use<, not<=. - Use index loops when you need positions, neighbours or in-place changes. Use
rangewhen only the values matter. - Go does not add an
intto a string with+: convert it withstrconv.Itoaor format it withfmt.Printf.