For the complete documentation index, see llms.txt. This page is also available as Markdown.

Context

Dalam aplikasi web, setiap request memiliki siklus hidupnya sendiri. Jika suatu request memakan waktu terlalu lama (misal karena database lambat atau koneksi jaringan bermasalah), kita perlu kemampuan untuk membatalkan proses tersebut.

Package context di Go menyediakan mekanisme standar untuk:

  • Mengirim sinyal pembatalan (cancellation)

  • Memberikan batas waktu (deadline)

  • Menyimpan nilai yang spesifik untuk request (request-scoped values)

πŸ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

πŸ”— github.com/jacky-htg/workshop/tree/main/14-context

14.1 Mengapa Context Penting?

Bayangkan skenario berikut:

  1. Client melakukan request GET /users

  2. Database sedang sibuk, query butuh 30 detik

  3. Client sudah timeout setelah 10 detik dan menutup koneksi

Tanpa context: Server tetap menjalankan query selama 30 detik, membuang resource.

Dengan context: Begitu koneksi client tertutup, context otomatis dibatalkan, dan query database bisa dihentikan.

14.2 Prinsip Dasar Context

Method
Kegunaan

Done()

Mengembalikan channel yang ditutup saat context selesai/batal

Err()

Mengembalikan alasan pembatalan (Canceled atau DeadlineExceeded)

Deadline()

Waktu kapan context akan otomatis batal

Value()

Mengambil nilai yang tersimpan di context

14.3 Aturan Emas Penggunaan Context

  1. Context adalah parameter pertama setiap fungsi yang melakukan operasi I/O atau berpotensi lama

  2. Jangan menyimpan context di struct – context harus di-passing sebagai parameter

  3. Gunakan context.Background() hanya di level tertinggi (main, test, init)

  4. Jangan gunakan nil context – gunakan context.TODO() jika belum tahu

  5. Context di HTTP handler berasal dari r.Context()

14.4 Implementasi Context di Repository

Semua method database harus menerima context.Context dan menggunakan method ...Context-nya:

Method database yang mendukung context:

  • QueryContext()

  • QueryRowContext()

  • ExecContext()

  • PrepareContext()

14.5 Propagasi Context ke Semua Layer

Service Layer

Handler Layer

14.6 Context di Logger

Logger juga perlu menerima context agar bisa menambahkan informasi request-specific (seperti request_id nantinya):

14.7 Context Cancellation Pattern (Referensi)

Untuk operasi yang benar-benar berat dan ingin mendukung pembatalan manual, gunakan pattern select dengan ctx.Done():

Contoh error yang mungkin dihasilkan:

  • context.Canceled – ketika cancel() dipanggil

  • context.DeadlineExceeded – ketika melebihi deadline

14.8 Handling Context Error dengan Gateway Timeout

Untuk operasi yang membutuhkan select dengan ctx.Done(), kita perlu mengembalikan error yang sesuai:

14.9 Aliran Context dalam Satu Request

14.10 Kode Lengkap yang Diubah

internal/repository/user_repository.go

internal/service/users.go

internal/handler/user_handler.go

pkg/response/response.go

pkg/errors/error.go

14.11 Perbandingan Sebelum dan Sesudah

Aspek
Sebelum
Sesudah

Parameter pertama

Tidak ada context

ctx context.Context

Database query

Query() / Exec()

QueryContext() / ExecContext()

Logger call

context.Background()

Meneruskan ctx

Timeout handling

Tidak ada (infinite)

Bisa dibatalkan via context

Request-scoped values

Tidak ada

Bisa pakai ctx.Value()

14.12 Catatan Penting

Untuk CRUD sederhana seperti di buku ini, kita tidak perlu menambahkan select dengan ctx.Done() secara manual karena:

  • Database driver sudah mendukung context cancellation

  • QueryContext() dan ExecContext() sudah internal mengecek ctx.Done()

Yang perlu diingat untuk masa depan:

  • Operasi I/O yang tidak punya dukungan context bawaan (file I/O, channel, goroutine manual) perlu select dengan ctx.Done()

  • Jika menemui kasus seperti itu, kembalikan errors.GatewayTimeout() agar client mendapat response 504

Ringkasan Bab 14

Di bab ini kita telah belajar:

Konsep
Implementasi

Context parameter

Parameter pertama di semua fungsi I/O

HTTP context

r.Context() sebagai sumber context

Database context

QueryContext(), ExecContext(), QueryRowContext()

Logger context

Semua log menerima context

Context propagation

Handler β†’ Service β†’ Repository

Manfaat yang kita peroleh:

  • βœ… Request dapat dibatalkan jika client disconnected

  • βœ… Database query berhenti ketika context batal (hemat resource)

  • βœ… Timeout bisa diatur di level HTTP server

  • βœ… Request-scoped values (seperti request_id) bisa di-passing

  • βœ… Siap untuk tracing (OpenTelemetry) yang membutuhkan context

Yang akan datang:

  • Saat ini input user masih diterima mentah-mentah

  • Bab selanjutnya: Validation – memvalidasi input sebelum diproses

Last updated