Skip to content

Beginner · Control flow and functions · topic 7 of 46 · 35 min

Loops: for is the only loop

Explanation

Go has exactly one loop keyword, for, used in three shapes: the classic counter loop, a while-style loop with just a condition, and an endless loop. for ... range walks over slices, strings, maps, channels and (since Go 1.22) plain integers. break leaves a loop and continue skips to the next round.

Why one loop is enough

Other languages have for, while and do-while. Go keeps only for, but it can be written in a few shapes that cover every need. Fewer keywords means less to learn and less to argue about.

Shape 1: the counter loop

go
for i := 1; i <= 5; i++ {
	fmt.Println("Roll number", i)
}
Three parts: init (runs once), condition (checked before each round), post (runs after each round). Prints roll numbers 1 to 5.

Shape 2: condition only (a while loop)

go
balance := 1000
months := 0
for balance > 0 {
	balance -= 300
	months++
}
fmt.Println(months, balance) // 4 -200
Keeps going while the condition is true.

Shape 3: forever, with break

go
attempt := 0
for {
	attempt++
	if attempt == 3 {
		fmt.Println("connected on attempt", attempt)
		break
	}
}
for { } runs until break or return. Servers and workers often loop like this.

for range: walking over things

range gives you each item of a collection. For a slice it gives the index and a copy of the value. Use the blank identifier _ to ignore one of them.

go
fruits := []string{"mango", "banana", "guava"}
for i, f := range fruits {
	fmt.Println(i, f)
}
for _, f := range fruits {
	fmt.Println(f)
}
Prints 0 mango, 1 banana, 2 guava, then the three names.
range overfirst valuesecond value
slice or arrayindexcopy of the element
stringbyte indexrune (a Unicode character)
mapkeyvalue (order is random)
channeleach received value(none)
integer n (Go 1.22+)0, 1, ..., n-1(none)
go
for i := range 3 {
	fmt.Println("try", i) // try 0, try 1, try 2
}
Range over an integer needs Go 1.22 or newer (and a go 1.22+ line in go.mod).
Careful: The value from range is a copy. for _, p := range prices { p = p * 2 } changes nothing in prices. To change the slice, use the index: for i := range prices { prices[i] *= 2 }.

break, continue and labels

go
for i := 1; i <= 10; i++ {
	if i%2 == 0 {
		continue // skip even numbers
	}
	if i > 7 {
		break    // stop the loop completely
	}
	fmt.Print(i, " ")
}
// prints: 1 3 5 7
continue jumps to the next round; break leaves the loop.

In nested loops, break only leaves the innermost loop. A label (a name followed by a colon) on the outer loop lets you break out of both.

go
outer:
for _, row := range [][]int{{1, 2}, {3, 4}} {
	for _, v := range row {
		if v == 3 {
			break outer
		}
		fmt.Println(v)
	}
}
Prints 1 and 2, then stops both loops at 3.

Go 1.22 change: a new loop variable each round

Before Go 1.22, a for loop had ONE variable i reused every round. Closures or goroutines that captured i all saw its final value, a famous bug. Since Go 1.22 each round gets its own copy, so the bug is gone for modules whose go.mod says go 1.22 or newer. You will still see old code with i := i inside loops; that line was the fix for the old behaviour.

Tip: Range over a string gives runes, not bytes. for i, r := range "₹50" gives r = '₹' at index 0, then '5' at index 3 (because ₹ takes 3 bytes in UTF-8), then '0' at index 4.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Loops: for is the only loop · 1/7

for: the only loop

Go has only one loop keyword: for. It comes in a few shapes.

Prefer a video by a teacher? Find free videos on “golang for loop range break continue tutorial” on YouTube ↗

In real life: Adding up a week of UPI spends

An expense app keeps each day's UPI spends in a slice. A range loop adds them up, skips refunds (negative numbers) with continue, and stops early with break if the weekly budget is crossed, so the app can warn the user.

go
package main

import "fmt"

func main() {
	spends := []int{120, 450, -80, 300, 999, 60}
	budget := 1500
	total := 0
	for day, amt := range spends {
		if amt < 0 {
			continue // refund, ignore here
		}
		total += amt
		if total > budget {
			fmt.Println("Budget crossed on day", day+1)
			break
		}
	}
	fmt.Println("Total:", total)
}
Prints Budget crossed on day 5, then Total: 1869.

Practice (0/4 done)

Task 1 · Question

What does this print? for i := 0; i < 3; i++ { fmt.Print(i, " ") }

Task 2 · Question

What is in nums after this? nums := []int{1, 2, 3} for _, n := range nums { n = n * 10 }

Task 3 · Question

What does this print? sum := 0 for i := range 5 { sum += i } fmt.Println(sum)

Task 4 · Practice

Print the multiplication table of 7 from 7 x 1 to 7 x 10, then use a while-style for loop to find how many months it takes to save Rs 10,000 at Rs 1,200 per month.

Quick quiz

Question 1

1.How do you write a while loop in Go?

Question 2

2.In a range over a map, what order do keys come in?

Question 3

3.In nested loops, what does a plain break do?

Question 4

4.What changed for loop variables in Go 1.22?

Question 5

5.Ranging over a string gives which second value?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

How do you write a while loop in Go?

Answer: for x < 10 { }

for with only a condition is Go's while loop.

In a range over a map, what order do keys come in?

Answer: Not specified; it can differ each run

Map iteration order is not specified and Go deliberately randomises it.

In nested loops, what does a plain break do?

Answer: Leaves only the innermost loop

Use a label (break outer) to leave an outer loop.

What changed for loop variables in Go 1.22?

Answer: Each iteration gets its own copy of the variable

Per-iteration variables fixed the classic closure-captures-the-last-value bug.

Ranging over a string gives which second value?

Answer: A rune (Unicode character)

range over a string decodes UTF-8 and gives runes.

What does break do inside a loop?Related

Answer: Exits the loop immediately

break leaves the innermost loop (or switch) at once.

From Loops: for, while, do-while and range-for

Which loop is safest for going over every item of an array?Related

Answer: for item in array

for cannot go past the end, so there are no index mistakes.

From Control flow: if, loop, while and for

How do you leave an outer loop from inside an inner loop?Related

Answer: A labelled break, like break outer;

Labels let break target an outer loop.

From Loops: for, while, do-while and for-each

Which loop always runs its body at least once?Related

Answer: do…while

do…while checks the condition after the first run.

From Loops: for, while, do…while, for…of and for…in

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Control flow and functions” before its exam: Functions and multiple return values, Variadic functions, function values and closures, defer: clean up at the end.
  2. Module 2 exam: Control flow and functions · 13 questions · 20 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Collections and structs. 46 topics left in the course before the final exam.

← Previous: Decisions with if and switch