Membuka Bungkus Error dengan `errors.Is`
Termasuk bagian Logika & Alur dalam perjalanan GO di Coddy. Pelajaran 40 dari 68.
Saat menangani error yang dibungkus, kamu perlu cara untuk memeriksa apakah error tertentu ada di bagian mana pun dalam rantai error. Fungsi errors.Is menyediakan kemampuan ini, sehingga kamu dapat mengidentifikasi error sentinel meskipun sudah dibungkus beberapa kali.
Fungsi errors.Is menerima dua parameter: error yang ingin kamu periksa dan error target yang kamu cari. Fungsi ini mengembalikan true jika error target ditemukan di mana saja dalam rantai error:
var ErrNotFound = errors.New("not found")
wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)
if errors.Is(wrappedErr, ErrNotFound) {
fmt.Println("This is a not found error")
}Ini adalah cara modern yang direkomendasikan untuk memeriksa error tertentu di Go. Tidak seperti perbandingan string atau pemeriksaan kesetaraan langsung, errors.Is bekerja dengan benar pada error yang dibungkus dan menelusuri rantai error untuk menemukan kecocokan. Hal ini membuat penanganan error-mu tangguh dan andal, bahkan saat error melewati beberapa lapisan aplikasimu.
Tantangan
MudahBangun sistem pemantauan koneksi database yang menggunakan errors.Is untuk mengidentifikasi error koneksi tertentu dalam rantai error yang dibungkus. Tantangan ini menunjukkan cara menggunakan errors.Is untuk mendeteksi error sentinel meskipun error tersebut telah dibungkus dengan konteks tambahan melalui beberapa lapisan aplikasi.
Kamu akan menerima dua input:
- String yang berisi detail operasi database dalam format
"database_name,operation,error_type"(misalnya,"users_db,connect,connection_timeout") - String yang berisi konteks aplikasi dalam format
"service_name,retry_count"(misalnya,"AuthService,3")
Tugasmu adalah:
- Definisikan tiga error sentinel menggunakan
errors.New():ErrConnectionTimeoutdengan pesan"connection timeout"ErrConnectionRefuseddengan pesan"connection refused"ErrDatabaseNotFounddengan pesan"database not found"
- Parse input pertama dengan memisahkannya berdasarkan koma untuk mendapatkan nama database, operasi, dan tipe error
- Parse input kedua dengan memisahkannya berdasarkan koma untuk mendapatkan nama layanan dan jumlah percobaan ulang
- Buat error asli berdasarkan tipe error:
- Jika tipe error adalah
"connection_timeout": gunakanErrConnectionTimeout - Jika tipe error adalah
"connection_refused": gunakanErrConnectionRefused - Jika tipe error adalah
"database_not_found": gunakanErrDatabaseNotFound - Untuk tipe error lainnya: gunakan
errors.New("unknown database error")
- Jika tipe error adalah
- Buat error terbungkus tingkat database menggunakan
fmt.Errorfdengan%w:"failed to [operation] database [database_name]: %w" - Buat error terbungkus tingkat layanan:
"[service_name] database operation failed after [retry_count] retries: %w" - Gunakan
errors.Isuntuk memeriksa apakah error terbungkus terakhir cocok dengan setiap error sentinel, lalu tampilkan hasilnya:"Checking for connection timeout: [true/false]""Checking for connection refused: [true/false]""Checking for database not found: [true/false]"
- Tampilkan rantai error:
"Error Chain:""Original: [original_error_message]""Database level: [database_level_error_message]""Service level: [service_level_error_message]"
- Tampilkan analisis error:
"Error Analysis:""Database: [database_name]""Operation: [operation]""Service: [service_name]""Retries: [retry_count]""Error type detected: [detected_error_type]"dengan detected_error_type berupa salah satu dari "Connection Timeout", "Connection Refused", "Database Not Found", atau "Unknown Error"
Gunakan package strings untuk memisahkan string input berdasarkan koma, package errors untuk error sentinel dan errors.Is, serta package fmt untuk membungkus error. Tantangan ini menunjukkan bahwa errors.Is menyediakan identifikasi error yang andal dan berfungsi dengan benar pada error yang dibungkus, sehingga penting untuk penanganan error yang dapat diandalkan dalam aplikasi kompleks.
Coba sendiri
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
// Baca input
var dbOperation string
var appContext string
fmt.Scanln(&dbOperation)
fmt.Scanln(&appContext)
// Uraikan input
dbParts := strings.Split(dbOperation, ",")
databaseName := dbParts[0]
operation := dbParts[1]
errorType := dbParts[2]
contextParts := strings.Split(appContext, ",")
serviceName := contextParts[0]
retryCount := contextParts[1]
// TODO: Tulis kodemu di bawah ini
// 1. Definisikan tiga sentinel error menggunakan errors.New()
// 2. Buat error asli berdasarkan jenis error
// 3. Buat error terbungkus pada tingkat database menggunakan fmt.Errorf dengan %w
// 4. Buat error terbungkus pada tingkat layanan
// 5. Gunakan errors.Is untuk memeriksa setiap sentinel error
// 6. Tampilkan hasil dan rantai error
}Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Logika & Alur
1Alur Kontrol Lanjutan
switch dengan `fallthrough`Keluar dari Perulangan BersarangMelanjutkan Perulangan TertentuPernyataan `goto`Rangkuman, Kontrol Perulangan Lanjutan4Proyek: Daftar Tugas Sederhana
Menyiapkan ProyekMenambahkan Tugas7Penanganan Error secara Mendalam
Tipe Error KustomMembungkus Error dengan `%w`Membuka Bungkus Error dengan `errors.Is`Membuka Bungkus Error dengan `errors.As`Memahami `panic`Menggunakan `recover`Rangkuman: Pembagian Aman2Struct dan Method
Mendefinisikan Method pada StructPenerima NilaiPenerima PointerMemilih PenerimaMethod vs FungsiRekap: Perilaku Struct5Map secara Mendalam
Map Berisi StructPointer sebagai Nilai MapMenguji Map NilMembandingkan MapRingkasan: Penghitung Frekuensi Kata8Proyek: Inventaris Sederhana
Gambaran Umum ProyekMemeriksa Stok3Interface (Dasar)
Apa Itu Interface?Mendefinisikan InterfaceMengimplementasikan InterfaceMenggunakan Tipe InterfaceInterface KosongType AssertionType SwitchRingkasan: Bentuk dan PerilakuLatihan sendiri: Compiler Go online