0Pricing
Go Academy · Pelajaran

Pembungkusan dan Pelepasan Error

Menggunakan %w, errors.Is, dan errors.As

Pembungkusan dan Pelepasan Error adalah pelajaran Go Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Go Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Go Academy mencakup 4 pelajaran total.

Apa Itu Pembungkusan Galat?

Pembungkusan galat menyematkan galat asli di dalam galat baru, mempertahankan galat asli untuk pemeriksaan terprogram sekaligus menambahkan konteks. Dukungan yang tepat diperkenalkan di Go 1.13:

package main
import ("fmt"; "errors")

var ErrDB = errors.New("database unreachable")

func queryUsers() error {
    return fmt.Errorf("queryUsers: %w", ErrDB)
}

func loadProfile(id int) error {
    return fmt.Errorf("loadProfile(%d): %w", id, queryUsers())
}

func main() {
    err := loadProfile(42)
    fmt.Println(err) // loadProfile(42): queryUsers: database unreachable
}

Kata Format %w

Gunakan %w (bukan %v) dalam fmt.Errorf untuk membungkus galat. Galat yang dibungkus dapat diakses melalui errors.Unwrap:

package main
import ("fmt"; "errors")

func main() {
    inner := errors.New("inner error")
    outer := fmt.Errorf("outer: %w", inner)

    fmt.Println(outer)              // outer: inner error
    fmt.Println(errors.Unwrap(outer)) // inner error
    fmt.Println(errors.Is(outer, inner)) // true
}

errors.Unwrap

errors.Unwrap mengembalikan galat berikutnya dalam rantai (galat yang dibungkus), atau nil jika tidak ada:

package main
import ("fmt"; "errors")

type Layer struct{ msg string; err error }
func (l *Layer) Error() string { return l.msg }
func (l *Layer) Unwrap() error { return l.err }

func main() {
    root := errors.New("root")
    mid  := &Layer{"mid", root}
    top  := &Layer{"top", mid}

    fmt.Println(errors.Unwrap(top))  // mid
    fmt.Println(errors.Unwrap(mid))  // root
    fmt.Println(errors.Unwrap(root)) // <nil>
}

errors.Is — Penelusuran Rantai

errors.Is(err, target) membuka bungkus rantai galat secara rekursif hingga menemukan kecocokan atau mencapai nil:

package main
import ("fmt"; "errors")

var ErrNotFound = errors.New("not found")

func findItem(id int) error {
    return fmt.Errorf("findItem(%d): %w",
        id, fmt.Errorf("repo: %w", ErrNotFound))
}

func main() {
    err := findItem(7)
    fmt.Println(errors.Is(err, ErrNotFound)) // true — deep in chain
    fmt.Println(err)                         // full message chain
}

errors.As — Penelusuran Rantai untuk Tipe

errors.As(err, &target) menelusuri rantai untuk mencari galat yang dapat ditetapkan ke tipe target:

package main
import ("fmt"; "errors")

type StatusError struct{ Code int }
func (e *StatusError) Error() string { return fmt.Sprintf("status %d", e.Code) }

func doRequest() error {
    return fmt.Errorf("request: %w", &StatusError{503})
}

func main() {
    err := doRequest()
    var se *StatusError
    if errors.As(err, &se) {
        fmt.Println("status code:", se.Code) // 503
    }
}

Unwrap Khusus untuk Rantai

Implementasikan Unwrap() error pada tipe galat khusus Anda untuk mendukung errors.Is dan errors.As:

package main
import ("fmt"; "errors")

type AppError struct {
    Op  string
    Err error
}
func (e *AppError) Error() string  { return fmt.Sprintf("%s: %v", e.Op, e.Err) }
func (e *AppError) Unwrap() error  { return e.Err }

var ErrAuth = errors.New("unauthorized")

func main() {
    err := &AppError{"login", ErrAuth}
    fmt.Println(errors.Is(err, ErrAuth)) // true
}

%v vs %w dalam fmt.Errorf

Perbedaan antara %v dan %w:

package main
import ("fmt"; "errors")

func main() {
    inner := errors.New("inner")

    withV := fmt.Errorf("outer: %v", inner) // string only, no wrap
    withW := fmt.Errorf("outer: %w", inner) // wraps inner

    fmt.Println(errors.Is(withV, inner)) // false — not wrapped
    fmt.Println(errors.Is(withW, inner)) // true  — wrapped
}

Pembungkusan dalam Praktik: handler HTTP

Pembungkusan galat yang konsisten memudahkan proses penelusuran masalah dalam sistem produksi:

package main
import "fmt"

func dbQuery(sql string) error {
    return fmt.Errorf("db.Query(%q): connection refused", sql)
}

func getUserByID(id int) (string, error) {
    if err := dbQuery("SELECT * FROM users WHERE id=?"); err != nil {
        return "", fmt.Errorf("getUserByID(%d): %w", id, err)
    }
    return "Alice", nil
}

func handler() error {
    _, err := getUserByID(1)
    if err != nil {
        return fmt.Errorf("handler: %w", err)
    }
    return nil
}

func main() { fmt.Println(handler()) }

errors.Join — Beberapa Pembungkus (Go 1.20+)

errors.Join membuat galat yang membungkus beberapa galat. errors.Is memeriksa semuanya:

package main
import ("fmt"; "errors")

var ErrA = errors.New("err A")
var ErrB = errors.New("err B")

func main() {
    joined := errors.Join(ErrA, ErrB)
    fmt.Println(joined)
    fmt.Println(errors.Is(joined, ErrA)) // true
    fmt.Println(errors.Is(joined, ErrB)) // true
}

Praktik Terbaik Membuka Bungkus Galat

Panduan untuk membungkus galat:

  • Bungkus dengan %w untuk mempertahankan galat agar dapat diperiksa secara terprogram
  • Tambahkan nama operasi sebagai konteks: fmt.Errorf("funcName: %w", err)
  • Jangan membungkus galat penanda jika pemanggil tidak akan menggunakan errors.Is
  • Hindari membungkus ganda konteks yang sama pada setiap tingkat
  • Implementasikan Unwrap() pada tipe khusus agar dapat berpartisipasi dalam rantai

Pemeriksaan Singkat

Apa perbedaan penggunaan %v dan %w dalam fmt.Errorf?

Ringkasan: Pembungkusan dan Pembukaan Bungkus Galat

Ringkasan:

  • fmt.Errorf("ctx: %w", err) membungkus dengan konteks
  • errors.Unwrap mendapatkan galat berikutnya dalam rantai
  • errors.Is menelusuri rantai untuk mencari kecocokan identitas
  • errors.As menelusuri rantai untuk mencari kecocokan tipe
  • Tipe khusus mengimplementasikan Unwrap() error
  • errors.Join membungkus beberapa galat (Go 1.20+)

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pembungkusan dan Pelepasan Error” gratis?

Ya — teks lengkap “Pembungkusan dan Pelepasan Error” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Go Academy, upgrade ke CoddyKit PRO. Kursus Go Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Pembungkusan dan Pelepasan Error”?

Menggunakan %w, errors.Is, dan errors.As Kamu berlatih Go Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Go Academy?

Tidak diperlukan pengalaman sebelumnya. Go Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Pembungkusan dan Pelepasan Error” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Go Academy ini?

Ya. Setiap pelajaran Go Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Interface error
  2. Membuat Error Khusus
  3. Pembungkusan dan Pelepasan Error
  4. panic, recover, dan defer
← Kembali ke Go Academy