🖥️ VS Code: Problems Panel untuk Error Real-time

Dengan extension Go, VS Code menampilkan semua error Go di panel Problems (tekan Ctrl+Shift+M) secara real-time saat kamu mengetik. Hover di atas garis merah di editor untuk melihat detail error. Klik Quick Fix (💡) untuk saran perbaikan otomatis.

Ini salah satu hal yang paling membedakan Go dari bahasa lain. Tidak ada try/catch/finally. Error adalah nilai biasa yang dikembalikan oleh fungsi — kamu wajib menanganinya secara eksplisit.

Kenapa Go Tidak Pakai try/catch?

Di banyak bahasa, exception bisa "terbang" melewati banyak layer tanpa terdeteksi sampai crash. Go memaksa developer menangani error di tempat yang tepat — hasilnya kode lebih eksplisit dan lebih mudah di-debug.

error Interface

error di Go adalah interface sederhana:

type error interface {
    Error() string
}

Setiap tipe yang punya method Error() string otomatis implementasi interface error.

Pola Dasar

import (
    "errors"
    "fmt"
)

func bagi(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("pembagi tidak boleh nol")
    }
    return a / b, nil
}

func main() {
    hasil, err := bagi(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Hasil:", hasil)
}

Pola if err != nil ini akan kamu temukan di setiap kode Go. Ini memang disengaja — Go percaya explicit is better than implicit.

fmt.Errorf — Buat Error dengan Konteks

func ambilUser(id int) (*User, error) {
    user, err := db.FindByID(id)
    if err != nil {
        // Wrap error dengan konteks tambahan (Go 1.13+)
        return nil, fmt.Errorf("ambilUser(%d): %w", id, err)
    }
    return user, nil
}

// Output error-nya jadi:
// "ambilUser(42): record not found"

%w (wrap) berbeda dengan %v — error yang di-wrap bisa di-unwrap dengan errors.Is dan errors.As.

Custom Error Type

// Definisi custom error
type ValidationError struct {
    Field   string
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validasi gagal pada field '%s': %s", e.Field, e.Message)
}

// Penggunaan
func validasiEmail(email string) error {
    if email == "" {
        return &ValidationError{Field: "email", Message: "tidak boleh kosong"}
    }
    if len(email) < 5 {
        return &ValidationError{Field: "email", Message: "terlalu pendek"}
    }
    return nil
}

errors.Is — Cek Jenis Error

var ErrNotFound = errors.New("tidak ditemukan")
var ErrUnauthorized = errors.New("tidak terautentikasi")

func ambilData(id int) error {
    return fmt.Errorf("ambilData: %w", ErrNotFound)  // wrap
}

err := ambilData(99)
if errors.Is(err, ErrNotFound) {
    fmt.Println("Data tidak ada, tampilkan 404")
} else if errors.Is(err, ErrUnauthorized) {
    fmt.Println("Perlu login dulu")
}

errors.As — Ekstrak Detail Error

err := validasiEmail("")

var valErr *ValidationError
if errors.As(err, &valErr) {
    fmt.Printf("Field: %s\n", valErr.Field)
    fmt.Printf("Pesan: %s\n", valErr.Message)
}

Panic & Recover

Panic adalah cara Go untuk menangani kesalahan yang benar-benar tidak terduga (seperti index out of range, nil pointer). Gunakan dengan hati-hati — ini bukan pengganti error handling biasa.

func paksa(nilai int) {
    if nilai < 0 {
        panic("nilai tidak boleh negatif!")  // program crash jika tidak di-recover
    }
}

// Recover harus ada di dalam defer
func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Panic ditangkap:", r)
        }
    }()

    paksa(-1)  // akan panic, tapi di-recover
    fmt.Println("Ini tidak akan tercetak")
}

func main() {
    safe()
    fmt.Println("Program tetap jalan")
}

Best Practice: Wrap Error, Jangan Ditelan

// ❌ Buruk — error ditelan, tidak ada informasi
if err != nil {
    return nil, errors.New("error")
}

// ❌ Buruk — error di-log tapi tetap di-return, nanti di-log lagi
if err != nil {
    log.Println(err)
    return nil, err
}

// ✅ Baik — wrap dengan konteks yang jelas
if err != nil {
    return nil, fmt.Errorf("createOrder(userID=%d): %w", userID, err)
}
💡 Ringkasan Kapan Pakai Apa
errors.New("...")Error sederhana tanpa konteks dinamis
fmt.Errorf("...: %w", err)Tambah konteks + wrap error asli
Custom error structError dengan data tambahan (field, code, dll)
errors.IsCek jenis error (termasuk yang di-wrap)
panic/recoverHanya untuk kondisi yang benar-benar tidak terduga