Menu
CoddyTech

Bọc lỗi bằng `%w`

Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 39 trên 68.

Khi ứng dụng gặp lỗi, bạn thường cần bổ sung ngữ cảnh khi lỗi đi qua các lớp khác nhau trong code. Go cung cấp một cơ chế mạnh mẽ để làm việc này: bọc lỗi bằng động từ định dạng %w với fmt.Errorf.

Việc bọc lỗi cho phép bạn thêm thông tin ngữ cảnh vào một lỗi hiện có mà vẫn giữ nguyên lỗi gốc bên dưới. Nhờ đó, ta tạo được một chuỗi lỗi lưu lại đầy đủ lịch sử về những gì đã xảy ra:

originalErr := errors.New("file not found")
wrappedErr := fmt.Errorf("failed to load config: %w", originalErr)

Động từ %w có chức năng đặc biệt: nó yêu cầu fmt.Errorf bọc lỗi thay vì chỉ chuyển lỗi thành chuỗi. Nhờ vậy, lỗi gốc được giữ lại để bạn có thể kiểm tra sau bằng các hàm như errors.Is và errors.As.

Mẫu này đặc biệt hữu ích trong các ứng dụng lớn, nơi một lỗi có thể đi qua nhiều hàm, mỗi hàm bổ sung thêm ngữ cảnh riêng. Ví dụ, lỗi kết nối cơ sở dữ liệu có thể được bọc thêm thông tin "failed to connect to database", rồi tiếp tục được bọc với thông tin "unable to start server", tạo thành một dấu vết rõ ràng về sự việc đã xảy ra và vị trí xảy ra.

challenge icon

Thử thách

Dễ

Xây dựng một hệ thống xử lý tệp, trong đó lỗi được bọc kèm thông tin ngữ cảnh khi truyền qua các lớp khác nhau của ứng dụng. Thử thách này hướng dẫn cách dùng động từ định dạng %w với fmt.Errorf để tạo chuỗi lỗi, giữ lại lỗi gốc và bổ sung ngữ cảnh có ý nghĩa.

Bạn sẽ nhận hai đầu vào:

  • Một chuỗi chứa thông tin chi tiết về thao tác với tệp theo định dạng "filename,operation,status" (ví dụ: "config.json,read,permission_denied")
  • Một chuỗi chứa ngữ cảnh hệ thống theo định dạng "service_name,component" (ví dụ: "UserService,ConfigLoader")

Nhiệm vụ của bạn là:

  1. Phân tích đầu vào thứ nhất bằng cách tách chuỗi theo dấu phẩy để lấy tên tệp, thao tác và trạng thái
  2. Phân tích đầu vào thứ hai bằng cách tách chuỗi theo dấu phẩy để lấy tên dịch vụ và thành phần
  3. Tạo lỗi gốc dựa trên trạng thái bằng errors.New():
    • Nếu trạng thái là "permission_denied": "permission denied"
    • Nếu trạng thái là "not_found": "file not found"
    • Nếu trạng thái là "corrupted": "file corrupted"
    • Với mọi trạng thái khác: "unknown error"
  4. Tạo lỗi được bọc ở cấp tệp bằng fmt.Errorf với %w: "failed to [operation] file [filename]: %w"
  5. Tạo lỗi được bọc ở cấp thành phần: "[component] error: %w"
  6. Tạo lỗi được bọc ở cấp dịch vụ: "[service_name] operation failed: %w"
  7. Hiển thị chuỗi lỗi bằng cách in ra từng cấp:
    • "Original error: [original_error_message]"
    • "File level: [file_level_error_message]"
    • "Component level: [component_level_error_message]"
    • "Service level: [service_level_error_message]"
  8. Hiển thị bản tóm tắt chuỗi lỗi:
    • "Error Chain Summary:"
    • "File: [filename]"
    • "Operation: [operation]"
    • "Component: [component]"
    • "Service: [service_name]"
    • "Root cause: [original_error_message]"

Dùng gói strings để tách các chuỗi đầu vào theo dấu phẩy, gói errors để tạo lỗi gốc và gói fmt để tạo lỗi được bọc. Thử thách này hướng dẫn cách bọc lỗi bằng %w tạo ra dấu vết ngữ cảnh rõ ràng khi lỗi đi qua các lớp khác nhau của ứng dụng, giúp việc gỡ lỗi hiệu quả hơn nhiều.

Tự làm thử

package main

import (
	"errors"
	"fmt"
	"strings"
)

func main() {
	// Đọc đầu vào
	var fileDetails string
	var systemContext string
	fmt.Scanln(&fileDetails)
	fmt.Scanln(&systemContext)
	
	// Phân tích các đầu vào
	fileInfo := strings.Split(fileDetails, ",")
	filename := fileInfo[0]
	operation := fileInfo[1]
	status := fileInfo[2]
	
	contextInfo := strings.Split(systemContext, ",")
	serviceName := contextInfo[0]
	component := contextInfo[1]
	
	// TODO: Viết code bên dưới
	// Tạo lỗi gốc dựa trên status
	// Tạo lỗi được bọc ở cấp tệp
	// Tạo lỗi được bọc ở cấp thành phần
	// Tạo lỗi được bọc ở cấp dịch vụ
	// In ra từng cấp lỗi và phần tóm tắt
	
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch Go online