Loops & Range
Loops allow you to execute code repeatedly. Go has only one looping
constructโthe
for loopโbut it's incredibly versatile. In this lesson, you'll
learn all the
ways to use for and the powerful range keyword for
iteration.
The For Loop
Go has only one loop keyword: for. It can be used in several ways:
Click Run to execute your code
for init; condition; post {
// loop body
}
- init: Executed before the first iteration (optional)
- condition: Evaluated before each iteration (optional)
- post: Executed at the end of each iteration (optional)
Classic For Loop
// Traditional C-style for loop
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// Count down
for i := 10; i > 0; i-- {
fmt.Println(i)
}
// Step by 2
for i := 0; i < 10; i += 2 {
fmt.Println(i) // 0, 2, 4, 6, 8
}
i) is scoped to
the loop. It's
not accessible outside the loop body.
While-Style Loops
Go doesn't have a while keyword, but you can use for as
a while
loop:
Click Run to execute your code
Infinite Loops
Omit all components to create an infinite loop:
// Infinite loop
for {
fmt.Println("This runs forever!")
// Use break to exit
if someCondition {
break
}
}
// Common pattern: server loops
for {
conn, err := listener.Accept()
if err != nil {
break
}
go handleConnection(conn)
}
The Range Keyword
The range keyword iterates over elements in various data structures:
Click Run to execute your code
Range Over Different Types
| Type | Syntax | Returns |
|---|---|---|
| Slice/Array | for i, v := range slice |
index, value |
| String | for i, r := range str |
index, rune |
| Map | for k, v := range map |
key, value |
| Channel | for v := range ch |
value |
Range Over Maps
Click Run to execute your code
Ignoring Values with Blank Identifier
// Only need the index
for i := range numbers {
fmt.Println("Index:", i)
}
// Only need the value
for _, value := range numbers {
fmt.Println("Value:", value)
}
// Only need keys from map
for key := range myMap {
fmt.Println("Key:", key)
}
Break and Continue
Control loop execution with break and continue:
Break - Exit the Loop
// Find first even number
for i := 1; i <= 10; i++ {
if i%2 == 0 {
fmt.Println("First even:", i)
break // Exit the loop
}
}
// Search in slice
for _, name := range names {
if name == "Alice" {
fmt.Println("Found Alice!")
break
}
}
Continue - Skip to Next Iteration
// Print only odd numbers
for i := 1; i <= 10; i++ {
if i%2 == 0 {
continue // Skip even numbers
}
fmt.Println(i)
}
// Skip empty strings
for _, str := range strings {
if str == "" {
continue
}
fmt.Println(str)
}
Labeled Breaks
Break out of nested loops using labels:
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i*j > 2 {
break outer // Breaks out of both loops
}
fmt.Printf("i=%d, j=%d\n", i, j)
}
}
Common Loop Patterns
1. Counting
// Count from 1 to 10
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
// Count down
for i := 10; i >= 1; i-- {
fmt.Println(i)
}
2. Sum/Accumulation
numbers := []int{1, 2, 3, 4, 5}
sum := 0
for _, num := range numbers {
sum += num
}
fmt.Println("Sum:", sum) // 15
3. Filtering
numbers := []int{1, 2, 3, 4, 5, 6}
var evens []int
for _, num := range numbers {
if num%2 == 0 {
evens = append(evens, num)
}
}
fmt.Println(evens) // [2, 4, 6]
4. Finding
names := []string{"Alice", "Bob", "Charlie"}
found := false
for _, name := range names {
if name == "Bob" {
found = true
break
}
}
fmt.Println("Found Bob:", found)
Common Mistakes
1. Modifying slice while iterating
// โ Dangerous - can cause issues
for i, v := range slice {
slice = append(slice, v*2) // Modifying while iterating!
}
// โ
Correct - iterate over a copy or use index-based loop
original := make([]int, len(slice))
copy(original, slice)
for _, v := range original {
slice = append(slice, v*2)
}
2. Range variable reuse
// โ Wrong - all pointers point to same variable
var ptrs []*int
for _, v := range []int{1, 2, 3} {
ptrs = append(ptrs, &v) // All point to same v!
}
// โ
Correct - create new variable
var ptrs []*int
for _, v := range []int{1, 2, 3} {
v := v // Create new variable
ptrs = append(ptrs, &v)
}
3. Infinite loop without break
// โ Wrong - runs forever
for {
fmt.Println("Forever!")
// No break condition!
}
// โ
Correct - have an exit condition
count := 0
for {
fmt.Println("Iteration:", count)
count++
if count >= 5 {
break
}
}
Exercise: FizzBuzz
Task: Implement the classic FizzBuzz problem.
Requirements:
- Loop from 1 to 30
- For multiples of 3, print "Fizz"
- For multiples of 5, print "Buzz"
- For multiples of both 3 and 5, print "FizzBuzz"
- Otherwise, print the number
Show Solution
package main
import "fmt"
func main() {
for i := 1; i <= 30; i++ {
// Check for both 3 and 5 first
if i%3 == 0 && i%5 == 0 {
fmt.Println("FizzBuzz")
} else if i%3 == 0 {
fmt.Println("Fizz")
} else if i%5 == 0 {
fmt.Println("Buzz")
} else {
fmt.Println(i)
}
}
// Alternative solution using string building
fmt.Println("\n--- Alternative ---")
for i := 1; i <= 30; i++ {
output := ""
if i%3 == 0 {
output += "Fizz"
}
if i%5 == 0 {
output += "Buzz"
}
if output == "" {
fmt.Println(i)
} else {
fmt.Println(output)
}
}
}
Summary
- for is the only loop in Go, but it's very versatile
- Classic for loop:
for init; condition; post - While-style loop:
for condition - Infinite loop:
for {} - range iterates over slices, arrays, strings, maps, and channels
- range on slice/array returns index and value
- range on map returns key and value (random order)
- break exits the loop, continue skips to next iteration
- Labeled breaks exit nested loops
What's Next?
Congratulations on completing the Control Flow module! You can now make decisions and repeat code. Next, you'll learn about Functions & Returns, where you'll discover how to organize code into reusable blocks and work with multiple return values.
Enjoying these tutorials?