Chuyển đến nội dung chính
Mô-đun 6 · Bài học 5 trong tổng số 530/50 trong khóa học~14 min
Bài học theo mô-đun (5/5)

Giao diện lỗi

error trong Go không phải là từ khóa: đó là giao diện tích hợp với phương pháp duy nhất.

Go
type error interface {
    Error() string
}

Bất cứ thứ gì có Error() string đều là error. Kết hợp với quy ước trả về (T, error) từ các hàm, đó là nền tảng xử lý lỗi trong Go.

Lỗi trọng điểm

Go
import "errors"

var ErrNotFound = errors.New("non trovato")

func find(key string) (string, error) {
    // ...
    return "", ErrNotFound
}

sentinel là giá trị error được xuất mà người gọi có thể so sánh để nhận biết trường hợp lỗi cụ thể.

Lỗi tùy chỉnh (có dữ liệu)

Để mang ngữ cảnh (ví dụ: khóa bị thiếu), bạn xác định một loại:

Go
type ErrNotFound struct {
    Key string
}

func (e *ErrNotFound) Error() string {
    return "non trovato: " + e.Key
}

func find(key string) (string, error) {
    return "", &ErrNotFound{Key: key}
}

lỗi.Là và lỗi.Như (Đi 1.13+)

So sánh với == chỉ có tác dụng đối với lính canh "thuần túy". Trở nên mạnh mẽ chống lại các lỗi được bao bọc, hãy sử dụng gói errors:

Go
import "errors"

if errors.Is(err, ErrNotFound) {
    // err IS ErrNotFound (even if wrapped)
}

var nfe *ErrNotFound
if errors.As(err, &nfe) {
    // err IS (or wraps) an *ErrNotFound; nfe points to the concrete value
    fmt.Println("chiave mancante:", nfe.Key)
}
  • errors.Is(err, target): đúng nếu mục tiêu ở đâu đó trong chuỗi gói.
  • errors.As(err, &target): gán để nhắm mục tiêu lỗi đầu tiên trong chuỗi thuộc loại của nó.

Gói bằng %w

Go
if err := find("k"); err != nil {
    return fmt.Errorf("operazione X: %w", err)
}

%w (KHÔNG phải %s hoặc %v) tạo ra lỗi mới bao bọc nguyên bản, giữ cho chuỗi có thể điều hướng được bằng errors.Is/As.

Mẫu xử lý

Go
v, err := op()
if err != nil {
    return fmt.Errorf("op fallita per %q: %w", id, err)
}

Thành ngữ:

  • Kiểm tra err != nil ngay lập tức, không có "con đường hạnh phúc sớm".
  • Thêm ngữ cảnh ở mỗi cấp độ bằng fmt.Errorf("... : %w", err).
  • "Ngược dòng" (gần main/handler), phân biệt đối xử với errors.Is/As.

Hãy thử nó

tập thể dục#go.m6.l5.e1
Nỗ lực: 0Đang tải…

Triển khai chuỗi Error() trên *ErrNotFound để nó trả về 'non trovato: <Key>'.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

`fmt.Println(err)` tự động gọi phương thức Error() trên cấu trúc của bạn.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#go.m6.l5.e2
Nỗ lực: 0Đang tải…

Sử dụng lỗi.Is để kiểm tra xem err có bằng ErrVuoto trọng điểm hay không.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

`errors.Is(err, target)` mạnh mẽ ngay cả với các chuỗi gói.

Giải pháp khả dụng sau 3 lần thử

Quiz#go.m6.l5.e3
Sẵn sàng

Chữ ký chính xác của phương pháp thực hiện lỗi là gì?

Go
func (e *MyErr) ??? {}
Tùy chọn trả lời

Tóm tắt lại

  • error = interface { Error() string }, tích hợp sẵn.
  • Cảnh báo có errors.New("...") dành cho các trường hợp đã biết mà không có ngữ cảnh.
  • Các loại lỗi tùy chỉnh với các trường mang ngữ cảnh.
  • errors.Is(err, target): so sánh mạnh mẽ với gói.
  • errors.As(err, &target): Khai thác loại bê tông.
  • fmt.Errorf("...: %w", err): bọc để bảo quản dây xích.
  • Không bao giờ %v / %s để bọc: LUÔN LUÔN sử dụng %w.