Chuyển tới nội dung chính

Cấu trúc điều khiển trong Go - Cách điều khiển luồng chương trình! 🎮

Chào mừng bạn đến với bài học về cấu trúc điều khiển trong Go! Đây là những công cụ giúp chương trình của bạn có thể "suy nghĩ" và "quyết định" giống như con người.

Cấu trúc điều khiển là gì? 🤔

Giống như khi bạn chơi game:

  • Nếu gặp quái vật, bạn sẽ đánh nhau
  • Nếu gặp đồng xu, bạn sẽ nhặt lên
  • Bạn sẽ lặp lại các hành động này cho đến khi kết thúc game

Trong lập trình, chúng ta cũng cần những cấu trúc tương tự để điều khiển luồng chương trình.

1. Câu lệnh if (Nếu...thì...) 🎯

if đơn giản

if x > 0 {
fmt.Println("x là số dương")
}

💡 Giải thích:

  • Giống như câu "Nếu trời mưa, tôi sẽ mang ô"
  • Chỉ thực hiện code trong dấu ngoặc nhọn khi điều kiện đúng

if với khởi tạo

if err := someFunction(); err != nil {
fmt.Println("Có lỗi:", err)
}

💡 Giải thích:

  • Giống như việc bạn kiểm tra bài tập trước khi nộp
  • Nếu có lỗi, báo cho người dùng biết

if-else (Nếu...thì...nếu không...)

if x > 0 {
fmt.Println("x là số dương")
} else {
fmt.Println("x là số âm hoặc 0")
}

💡 Giải thích:

  • Giống như câu "Nếu trời mưa, tôi sẽ mang ô; nếu không, tôi sẽ đi bộ"

if-else if-else (Nhiều điều kiện)

if x > 0 {
fmt.Println("x là số dương")
} else if x < 0 {
fmt.Println("x là số âm")
} else {
fmt.Println("x là 0")
}

💡 Giải thích:

  • Giống như việc phân loại điểm số:
    • 0: Điểm dương

    • < 0: Điểm âm
    • = 0: Điểm không

2. Vòng lặp for (Lặp lại) 🔄

for đơn giản

for i := 0; i < 10; i++ {
fmt.Println(i)
}

💡 Giải thích:

  • Giống như việc đếm từ 0 đến 9
  • i := 0: Bắt đầu từ 0
  • i < 10: Tiếp tục khi i nhỏ hơn 10
  • i++: Tăng i lên 1 sau mỗi lần lặp

for như while

for x > 0 {
x--
}

💡 Giải thích:

  • Giống như việc đếm ngược
  • Tiếp tục khi x còn lớn hơn 0
  • Mỗi lần lặp giảm x đi 1

for vô hạn

for {
// code
break // thoát vòng lặp
}

💡 Giải thích:

  • Giống như một vòng lặp không có điểm dừng
  • Cần có lệnh break để thoát
  • Sử dụng khi không biết trước số lần lặp

for range (Duyệt qua tập hợp)

// Duyệt qua slice
fruits := []string{"apple", "banana", "orange"}
for index, value := range fruits {
fmt.Printf("Index: %d, Value: %s\n", index, value)
}

// Duyệt qua map
m := map[string]int{"a": 1, "b": 2}
for key, value := range m {
fmt.Printf("Key: %s, Value: %d\n", key, value)
}

💡 Giải thích:

  • Giống như việc đọc từng trang trong một quyển sách
  • index: Vị trí của phần tử
  • value: Giá trị của phần tử

3. Câu lệnh switch (Chọn một trong nhiều) 🎲

switch đơn giản

switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s\n", os)
}

💡 Giải thích:

  • Giống như việc chọn môn học theo ngày:
    • Thứ 2: Toán
    • Thứ 3: Văn
    • Các ngày khác: Môn khác

switch không có điều kiện

switch {
case x > 0:
fmt.Println("x là số dương")
case x < 0:
fmt.Println("x là số âm")
default:
fmt.Println("x là 0")
}

💡 Giải thích:

  • Giống như việc phân loại điểm số
  • Mỗi case là một điều kiện riêng
  • default là trường hợp còn lại

switch với fallthrough

switch x {
case 1:
fmt.Println("x = 1")
fallthrough
case 2:
fmt.Println("x = 2")
}

💡 Giải thích:

  • Giống như việc chọn nhiều môn học cùng lúc
  • fallthrough: Tiếp tục thực hiện case tiếp theo

4. break và continue (Điều khiển vòng lặp) 🛑⏭️

break (Dừng vòng lặp)

for i := 0; i < 10; i++ {
if i == 5 {
break // thoát vòng lặp
}
fmt.Println(i)
}

💡 Giải thích:

  • Giống như việc dừng chơi game khi thua
  • Thoát hoàn toàn khỏi vòng lặp

continue (Bỏ qua lần lặp)

for i := 0; i < 10; i++ {
if i == 5 {
continue // bỏ qua lần lặp hiện tại
}
fmt.Println(i)
}

💡 Giải thích:

  • Giống như việc bỏ qua một câu hỏi khó trong bài thi
  • Tiếp tục với lần lặp tiếp theo

5. goto (Nhảy đến vị trí) 🎯

func main() {
i := 0
loop:
if i < 10 {
fmt.Println(i)
i++
goto loop
}
}

💡 Giải thích:

  • Giống như việc đánh dấu trang và quay lại đọc
  • Không nên sử dụng nhiều vì code khó đọc

Best Practices (Cách viết code tốt) 🌟

1. Sử dụng if với khởi tạo

// ✅ Tốt
if err := someFunction(); err != nil {
fmt.Println("Có lỗi:", err)
}

// ❌ Không tốt
err := someFunction()
if err != nil {
fmt.Println("Có lỗi:", err)
}

💡 Lý do: Code ngắn gọn và rõ ràng hơn

2. Sử dụng for range khi duyệt qua slice hoặc map

// ✅ Tốt
for index, value := range items {
fmt.Printf("%d: %s\n", index, value)
}

// ❌ Không tốt
for i := 0; i < len(items); i++ {
fmt.Printf("%d: %s\n", i, items[i])
}

💡 Lý do: Dễ đọc và ít mắc lỗi hơn

3. Sử dụng switch thay vì nhiều if-else

// ✅ Tốt
switch {
case x > 0:
fmt.Println("Dương")
case x < 0:
fmt.Println("Âm")
default:
fmt.Println("Không")
}

// ❌ Không tốt
if x > 0 {
fmt.Println("Dương")
} else if x < 0 {
fmt.Println("Âm")
} else {
fmt.Println("Không")
}

💡 Lý do: Code rõ ràng và dễ bảo trì hơn

Những lỗi thường gặp và cách sửa 🔧

  1. Lỗi: Quên dấu ngoặc nhọn trong if

    // ❌ Sai
    if x > 0
    fmt.Println("x là số dương")

    // ✅ Đúng
    if x > 0 {
    fmt.Println("x là số dương")
    }
  2. Lỗi: Vòng lặp vô hạn

    // ❌ Sai
    for i := 0; i < 10; i++ {
    // quên tăng i
    }

    // ✅ Đúng
    for i := 0; i < 10; i++ {
    // code
    }
  3. Lỗi: Quên break trong vòng lặp vô hạn

    // ❌ Sai
    for {
    // code
    }

    // ✅ Đúng
    for {
    // code
    if someCondition {
    break
    }
    }

Tiếp theo 🎯

Trong bài học tiếp theo, chúng ta sẽ:

  • Tìm hiểu về functions (hàm)
  • Học cách tổ chức code thành các package
  • Khám phá cách xử lý lỗi

💡 Lời khuyên: Hãy thử viết các chương trình đơn giản sử dụng các cấu trúc điều khiển khác nhau để hiểu rõ hơn về cách chúng hoạt động!