errors.Is() dan errors.As()
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 56 dari 107.
Saat error dibungkus, pemeriksaan kesetaraan sederhana seperti err == ErrNotFound tidak lagi berfungsi. Package errors menyediakan dua fungsi untuk memeriksa rantai error yang dibungkus: errors.Is() dan errors.As().
errors.Is() memeriksa apakah ada error dalam rantai yang cocok dengan sentinel error tertentu:
import "errors"
var ErrNotFound = errors.New("not found")
func FindUser(id int) error {
return fmt.Errorf("database lookup failed: %w", ErrNotFound)
}
err := FindUser(42)
if errors.Is(err, ErrNotFound) {
fmt.Println("User doesn't exist")
}Meskipun error yang dikembalikan dibungkus, errors.Is() mengurai rantainya dan menemukan ErrNotFound di dalamnya.
errors.As() memeriksa apakah ada error dalam rantai yang cocok dengan tipe tertentu, lalu mengekstraknya:
type ValidationError struct {
Field string
}
func (e *ValidationError) Error() string {
return "validation failed: " + e.Field
}
err := fmt.Errorf("request failed: %w", &ValidationError{Field: "email"})
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("Invalid field:", ve.Field)
}Gunakan errors.Is() saat memeriksa error sentinel, dan errors.As() saat kamu perlu mengakses field dari tipe error kustom. Kedua fungsi ini menelusuri seluruh rantai error, sehingga penting untuk menangani error yang dibungkus dengan benar.
Tantangan
MudahMari buat sistem pemrosesan file yang menunjukkan cara memeriksa rantai error yang dibungkus dengan benar menggunakan errors.Is() dan errors.As(). Kamu akan membuat error yang dibungkus saat melewati lapisan berbeda, lalu menggunakan fungsi-fungsi ini untuk mengidentifikasi dan mengambil informasi darinya.
Kamu akan menyusun kodemu dalam dua file:
errors.go: Tentukan infrastruktur error untuk sistem file-mu.Buat error sentinel:
ErrPermissionDenieddengan pesan"permission denied"
Buat tipe error khusus:
- struct
FileErrordengan fieldFilename(string) danOperation(string) - method
Error()-nya harus mengembalikan:[Operation] failed on file: [Filename]
Implementasikan dua fungsi yang menyimulasikan operasi file dan membungkus error:
ReadFile(filename string) error- Jika filename adalah"secret.txt", kembalikanErrPermissionDenied. Jika filename adalah"missing.txt", kembalikan*FileErrordengan Operation"read"dan Filename yang diberikan. Jika tidak, kembalikannil.ProcessFile(filename string) error- MemanggilReadFile. Jika sebuah error dikembalikan, bungkus menggunakanfmt.Errorfdengan format"processing failed: %w". Jika tidak, kembalikannil.
main.go: Baca nama file dari input dan panggilProcessFile. Gunakanerrors.Is()danerrors.As()untuk memeriksa rantai error yang dibungkus dan mencetak pesan yang sesuai berdasarkan isinya.
Input berikut akan diberikan:
- Baris 1: Nama file yang akan diproses
Tangani hasilnya dengan memeriksa rantai error:
- Jika
errors.Is()menemukanErrPermissionDenieddalam rantai: cetak pesan error lengkap, lalu cetakAccess denied - check file permissionspada baris baru - Jika
errors.As()menemukan*FileErrordalam rantai: cetak pesan error lengkap, lalu cetakFile issue: [Filename] during [Operation]pada baris baru - Jika tidak terjadi error: cetak
File '[filename]' processed successfully
Misalnya, jika diberi secret.txt, output-mu seharusnya seperti ini:
processing failed: permission denied
Access denied - check file permissionsJika diberi missing.txt, output-mu seharusnya seperti ini:
processing failed: read failed on file: missing.txt
File issue: missing.txt during readJika diberi data.txt, output-mu seharusnya seperti ini:
File 'data.txt' processed successfullyPerhatikan bahwa meskipun error dibungkus oleh ProcessFile, kamu tetap dapat mendeteksi error sentinel asli dengan errors.Is() dan mengambil tipe error khusus dengan errors.As(). Fungsi-fungsi ini menelusuri seluruh rantai error untuk menemukan yang kamu cari.
Coba sendiri
package main
import (
"errors"
"fmt"
)
func main() {
// Baca nama file dari input
var filename string
fmt.Scanln(&filename)
// Panggil ProcessFile dengan nama file tersebut
err := ProcessFile(filename)
// TODO: Tangani hasilnya dengan memeriksa rantai error
//
// Gunakan errors.Is() untuk memeriksa apakah ErrPermissionDenied ada dalam rantai error:
// - Jika ditemukan: cetak error lengkap, lalu "Access denied - check file permissions"
//
// Gunakan errors.As() untuk memeriksa apakah *FileError ada dalam rantai error:
// - Jika ditemukan: cetak error lengkap, lalu "File issue: [Filename] during [Operation]"
//
// Jika tidak ada error: cetak "File '[filename]' processed successfully"
_ = errors.Is // petunjuk: gunakan errors.Is()
_ = errors.As // petunjuk: gunakan errors.As()
_ = err
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online