Series Go Backend: Control Flow - If-else, Switch-case và vòng lặp For
Go đơn giản hóa tối đa các cấu trúc điều khiển luồng (Control Flow) bằng cách loại bỏ những cú pháp rườm rà (như dấu ngoặc đơn xung quanh điều kiện) và gộp toàn bộ các loại vòng lặp (while, do-while) vào một từ khóa duy nhất là for.
1. Cấu trúc If-else và "Short Statement"
Cú pháp cơ bản của if-else trong Go rất giống C++ hay PHP, nhưng bạn không cần bao bọc điều kiện trong cặp ngoặc đơn (). Tuy nhiên, cặp ngoặc nhọn {} là bắt buộc, ngay cả khi block code chỉ có một dòng.
Go
age := 22
if age >= 18 {
fmt.Println("Đủ tuổi truy cập hệ thống")
} else {
fmt.Println("Từ chối truy cập")
}
Đặc sản của Go: If statement initialization Go cho phép bạn khai báo và gán giá trị cho một biến ngay trước khi kiểm tra điều kiện, phân cách bằng dấu chấm phẩy ;. Biến được khai báo theo cách này sẽ chỉ tồn tại (scope) trong phạm vi của khối lệnh if và else đó.
Đây là pattern phổ biến nhất trong Go Backend, đặc biệt là khi xử lý lỗi (Error Handling) lúc query database hoặc call API:
Go
// Gọi hàm getUserById, lấy kết quả gán vào biến user và err
// Sau đó kiểm tra ngay xem err có khác nil hay không
if user, err := getUserById(1024); err != nil {
fmt.Println("Lỗi khi lấy thông tin user:", err)
return
} else {
// Biến user chỉ có thể sử dụng được bên trong block if-else này
fmt.Println("Tên user là:", user.Name)
}
// fmt.Println(user.Name) // Lỗi: undefined: user
2. Switch-case: Thông minh và an toàn hơn
switch trong Go khắc phục được "tử huyệt" của C++: Implicit Break. Bạn không cần phải viết từ khóa break ở cuối mỗi case nữa. Khi một case khớp điều kiện, Go sẽ thực thi block đó và tự động thoát khỏi switch.
Nhóm nhiều giá trị vào một case:
Go
status := "PENDING"
switch status {
case "PENDING", "PROCESSING":
fmt.Println("Đơn hàng đang được xử lý")
case "DELIVERED":
fmt.Println("Giao hàng thành công")
default:
fmt.Println("Trạng thái không hợp lệ")
}
Switch không có điều kiện (Switch true): Nếu bỏ qua biến sau từ khóa switch, Go mặc định hiểu là switch true. Kỹ thuật này giúp thay thế cho một chuỗi if-else if dài ngoằng, làm code clean hơn rất nhiều.
Go
score := 85
switch {
case score >= 90:
fmt.Println("Hạng A")
case score >= 80:
fmt.Println("Hạng B")
case score >= 70:
fmt.Println("Hạng C")
default:
fmt.Println("Cần cố gắng thêm")
}
(Lưu ý: Nếu bạn thực sự muốn logic chạy "tràn" xuống case tiếp theo giống hệt C++, bạn có thể dùng từ khóa fallthrough ở cuối case).
3. Vòng lặp For: "Một cho tất cả"
Go từ chối đưa vào ngôn ngữ các từ khóa while hay do-while. Thay vào đó, for đảm nhận toàn bộ trọng trách lặp với 3 biến thể chính:
Biến thể 1: Vòng lặp C-style truyền thống Gồm 3 phần: Khởi tạo; Điều kiện; Bước nhảy.
Go
for i := 0; i < 5; i++ {
fmt.Println("Lần lặp thứ:", i)
}
Biến thể 2: Đóng vai trò của "while" loop Bỏ qua phần khởi tạo và bước nhảy, chỉ giữ lại điều kiện.
Go
retryCount := 0
for retryCount < 3 {
fmt.Println("Đang thử lại kết nối DB lần...", retryCount+1)
retryCount++
}
Biến thể 3: Vòng lặp vô tận (Infinite loop) Bỏ qua hoàn toàn các điều kiện. Trong backend, pattern vòng lặp vô tận này đặc biệt hữu dụng khi bạn viết các Background Worker (ví dụ: liên tục lắng nghe job mới từ Beanstalkd, Kafka, hoặc xử lý các Goroutines).
Go
for {
msg := consumeKafkaMessage()
if msg == nil {
break // Thoát khỏi vòng lặp nếu không còn message
}
if msg.Type == "IGNORE" {
continue // Bỏ qua lượt này, chạy sang lượt lặp tiếp theo
}
processMessage(msg)
}
(Trong bài sau, chúng ta sẽ học thêm biến thể thứ 4 của vòng lặp for kết hợp với từ khóa range để duyệt qua các mảng/slice và map).
All rights reserved