A loop runs a block of code repeatedly. Most languages have several loop keywords — for, while, do-while, foreach. Go has just one: for. But that single keyword covers every looping pattern you’ll ever need.
The classic for loop
The full form has three parts separated by semicolons: an init, a condition, and a post:
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println("i =", i)
}
}
i = 0
i = 1
i = 2
i = 3
i = 4
What happens, step by step:
- Init (
i := 0) — runs once, before the loop starts - Condition (
i < 5) — checked before each iteration. Iffalse, the loop ends. - Body — runs while the condition is
true - Post (
i++) — runs after each iteration, before the next condition check
This is the same pattern as for in C, Java, or JavaScript — just without the parentheses.
for as a while loop
Drop the init and post and you’ve got a while loop:
// inside main()
n := 10
for n > 0 {
fmt.Println(n)
n--
}
10
9
8
...
1
Go doesn’t have a while keyword — for with just a condition is the equivalent.
Infinite loop
Drop the condition entirely and the loop runs forever — until you explicitly stop it:
// inside main()
count := 0
for {
count++
if count == 3 {
break
}
fmt.Println("Iteration", count)
}
fmt.Println("Done")
Iteration 1
Iteration 2
Done
Two new keywords appeared:
break— immediately exits the loopcontinue(which we’ll see in a moment) — skips the rest of the current iteration and goes back to the condition check
break and continue
package main
import "fmt"
func main() {
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue
}
if i > 7 {
break
}
fmt.Println(i)
}
}
1
3
5
7
Walk through it:
i = 1→ odd, less than 7 → printi = 2→ even →continue→ skip to next iterationi = 3→ odd, less than 7 → print- …
i = 7→ odd, not greater than 7 → printi = 8→ even →continue→ secondifnever runsi = 9→ odd, but9 > 7→break→ loop exits (soi = 10is never reached)
Subtle, right? That’s why running these examples and changing them is the only way to truly grasp loops.
Looping over a range
Often you don’t care about counter mechanics — you just want to walk through a collection. The range keyword does this:
package main
import "fmt"
func main() {
fruits := []string{"apple", "banana", "cherry"}
for index, fruit := range fruits {
fmt.Println(index, fruit)
}
}
0 apple
1 banana
2 cherry
range returns two values per iteration — the index and the value. (We’re using a slice here, which we’ll cover properly in the next section. For now, treat []string{...} as “a list of strings”.)
If you only care about the value, ignore the index with _:
// inside main()
for _, fruit := range fruits {
fmt.Println(fruit)
}
If you only care about the index (rare, but possible):
// inside main()
for index := range fruits {
fmt.Println(index)
}
The blank identifier _ is Go’s way of saying “I know there’s a value here but I don’t want it.” Use it whenever you need to discard something.
A practical example
Let’s combine everything we’ve learned in this section into one complete program — counting how many even numbers are between 1 and 20:
package main
import "fmt"
func main() {
evens := 0
for i := 1; i <= 20; i++ {
if i%2 != 0 {
continue
}
evens++
}
fmt.Println("There are", evens, "even numbers between 1 and 20")
}
There are 10 even numbers between 1 and 20
It uses a for loop, an if with a comparison and modulo, and continue — every concept from this section in 12 lines.
What’s next
You’ve now covered every fundamental piece of Go’s syntax: variables, types, operators, conditionals, and loops. Programs aren’t just made of single values, though — real software works with collections of data. That’s the next section: arrays, slices, maps, pointers, and structs.