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)
}