Vòng Lặp for

Go chỉ có một từ khóa vòng lặp: for

Không có while, do-while, foreach. Chỉ có for — nhưng rất linh hoạt.

Dạng 1: C-style for

for i := 0; i < 5; i++ {
    fmt.Println(i)
}
// Output: 0 1 2 3 4

Dạng 2: while-style (chỉ có điều kiện)

n := 1
for n < 1000 {
    n *= 2
}
fmt.Println(n) // 1024

Dạng 3: Vòng lặp vô hạn

for {
    input := readInput()
    if input == "quit" {
        break
    }
    process(input)
}

Dạng 4: for range — duyệt các collection

// Duyệt slice — lấy cả index và value
fruits := []string{"táo", "chuối", "cam"}
for i, fruit := range fruits {
    fmt.Printf("%d: %s\n", i, fruit)
}

// Chỉ cần value, bỏ index
for _, fruit := range fruits {
    fmt.Println(fruit)
}

// Chỉ cần index
for i := range fruits {
    fmt.Println(i)
}

// Duyệt map
ages := map[string]int{"An": 20, "Bình": 25}
for name, age := range ages {
    fmt.Printf("%s: %d tuổi\n", name, age)
}

// Duyệt string theo rune (ký tự Unicode)
for i, r := range "Xin chào" {
    fmt.Printf("[%d] %c\n", i, r)
}

break và continue

// continue: bỏ qua lần lặp hiện tại
for i := 0; i < 10; i++ {
    if i%2 == 0 { continue }  // bỏ qua số chẵn
    fmt.Println(i)             // in 1, 3, 5, 7, 9
}

// break: thoát khỏi vòng lặp
for i := 0; i < 100; i++ {
    if i*i > 50 {
        fmt.Println("Dừng tại i =", i)
        break
    }
}

Label — break/continue vòng ngoài

outer:
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        if i+j == 3 {
            break outer  // thoát cả vòng ngoài
        }
        fmt.Printf("(%d,%d) ", i, j)
    }
}

Cạm bẫy phổ biến: Khi dùng goroutine trong vòng lặp, biến vòng lặp bị share — dùng i := i để tạo bản copy.

example.go
package main

import "fmt"

func main() {
	// Tính số nguyên tố bằng Sieve of Eratosthenes
	n := 50
	sieve := make([]bool, n+1)
	for i := range sieve {
		sieve[i] = true
	}
	sieve[0], sieve[1] = false, false

	for i := 2; i*i <= n; i++ {
		if sieve[i] {
			for j := i * i; j <= n; j += i {
				sieve[j] = false
			}
		}
	}

	fmt.Printf("Số nguyên tố đến %d:\n", n)
	count := 0
	for i, prime := range sieve {
		if prime {
			fmt.Printf("%3d", i)
			count++
			if count%10 == 0 {
				fmt.Println()
			}
		}
	}
	fmt.Printf("\nTổng cộng: %d số\n", count)
}