Persiapan Proyek Go Fiber v3 dan Modul

Sebelum menambahkan ORM, pastikan proyek Go Anda telah menggunakan Go Fiber v3 sebagai web framework. Jika belum memiliki folder proyek, buat dulu dengan go mod init untuk menginisialisasi modul:

mkdir fiber-gorm-example
cd fiber-gorm-example
go mod init github.com/username/fiber-gorm-example

Perintah di atas menghasilkan file go.mod tempat Go menyimpan dependensi. Pastikan versi Go Anda sudah mendukung Go Fiber v3 (Go 1.21+ direkomendasikan) agar fitur Fiber terbaru dapat berjalan stabil.

Dengan modul sudah siap, tambahkan Fiber versi v3 jika belum:

go get github.com/gofiber/fiber/v3

Langkah ini memastikan dasar aplikasi Fiber siap sebelum Anda menambahkan ORM.

Instalasi GORM dan Driver PostgreSQL

GORM menyediakan abstraksi database ringan dengan integrasi ke banyak driver. Untuk contoh ini kita menghubungkan ke PostgreSQL, yang populer di aplikasi backend.

Tambahkan dependensi GORM dan driver PostgreSQL melalui go get:

go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres

Perintah tersebut mengunduh paket GORM dan driver PostgreSQL. Setelah selesai, Anda bisa mengimpor keduanya dalam file seperti main.go atau modul init database Anda:

import (
    "gorm.io/gorm"
    "gorm.io/driver/postgres"
)

Pastikan tidak mengimpor driver lain yang tidak digunakan agar modul tetap ringan.

Konfigurasi Database dan Environment Variable

Menyimpan informasi sensitif seperti kredensial di environment variable jauh lebih aman daripada menulis langsung di kode. Buat file konfigurasi lingkungan seperti .env yang tidak di-commit ke version control:

DB_HOST=localhost
DB_PORT=5432
DB_USER=fiber_user
DB_PASS=securepassword
DB_NAME=fiber_db
DB_SSLMODE=disable

Gunakan library seperti github.com/joho/godotenv jika ingin memuat file tersebut saat aplikasi dijalankan (opsional untuk produksi yang sudah memiliki mekanisme env populer). Di Fiber, Anda bisa memuat env pada main sebelum koneksi database:

if err := godotenv.Load(); err != nil {
    log.Println(".env file not found, relying on environment variables")
}

Setelah env dimuat, bentuk connection string yang dibutuhkan PostgreSQL:

dsn := fmt.Sprintf(
    "host=%s user=%s password=%s dbname=%s port=%s sslmode=%s",
    os.Getenv("DB_HOST"),
    os.Getenv("DB_USER"),
    os.Getenv("DB_PASS"),
    os.Getenv("DB_NAME"),
    os.Getenv("DB_PORT"),
    os.Getenv("DB_SSLMODE"),
)

Penggunaan fmt.Sprintf menjaga format string tetap konsisten dan memudahkan debugging jika ada value yang kosong atau salah.

Inisialisasi Koneksi GORM dengan Connection Pooling

Setelah DSN siap, buka koneksi GORM dengan driver PostgreSQL. Sekali koneksi dibuat, atur pooling agar database tetap sehat di lingkungan produksi:

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
    log.Fatalf("Gagal membuka koneksi database: %v", err)
}

sqlDB, err := db.DB()
if err != nil {
    log.Fatalf("Gagal mengambil handle SQL database: %v", err)
}

sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(50)
sqlDB.SetConnMaxLifetime(30 * time.Minute)

if err := sqlDB.Ping(); err != nil {
    log.Fatalf("Tidak bisa melakukan ping ke database: %v", err)
}

Penjelasan tiap pengaturan:

  • SetMaxIdleConns menjaga pool idle tetap siap melayani permintaan baru tanpa overhead membuat koneksi baru.
  • SetMaxOpenConns membatasi total koneksi aktif ke database dan mencegah overloading.
  • SetConnMaxLifetime memastikan koneksi lama tidak digunakan terus-menerus, mengurangi masalah stale connection pada database level.

Fungsi sqlDB.Ping() sangat penting untuk validasi awal. Dengan melakukan ping, aplikasi dapat mendeteksi masalah kredensial, akses jaringan, atau naming service sebelum Fiber menerima request.

Auto Ping Bersifat Proaktif

Tambahkan goroutine pendamping yang melakukan auto ping berkala untuk menjaga connection pool tetap sehat, terutama saat idle lama:

go func() {
    ticker := time.NewTicker(5 * time.Minute)
    defer ticker.Stop()
    for range ticker.C {
        if err := sqlDB.Ping(); err != nil {
            log.Printf("Warning: ping database gagal: %v", err)
        }
    }
}()

Auto ping tidak menggantikan monitoring, tapi membantu mencegah koneksi yang sudah mati terpakai kembali tanpa diketahui.

Validasi Koneksi dan Troubleshooting

Memastikan koneksi GORM berjalan lancar memerlukan pengecekan menyeluruh dan strategi penanganan error.

Pengecekan Awal

Setelah Ping sukses, Anda bisa menerapkan migrasi otomatis:

type User struct {
    ID   uint   `gorm:"primaryKey"`
    Name string `gorm:"size:100;not null"`
}

if err := db.AutoMigrate(&User{}); err != nil {
    log.Fatalf("AutoMigrate gagal: %v", err)
}

Auto migration membantu memastikan struktur tabel sesuai model tanpa harus menjalankan SQL manual. Namun, di lingkungan produksi besar, pertimbangkan menggunakan migration tool eksternal untuk kontrol versi schema.

Penanganan Error Konektivitas

Jika koneksi gagal karena alasan jaringan atau kredensial, tangani dengan logging cukup detail namun hindari mengekspos password di log. Contoh terjadi saat gorm.Open error:

if err != nil {
    log.Printf("Koneksi database gagal: %v", err)
    return err
}

Untuk diagnosa lanjut, cek pesan error pada log PostgreSQL; seringkali menunjukkan apakah masalah berasal dari autentikasi, host tidak ditemukan, atau batas koneksi.

Trade-off dan Praktik Terbaik

GORM memudahkan dengan abstraksi ORM, tetapi ada trade-off terhadap kontrol SQL halus (misalnya query kompleks). Gunakan GORM dengan custom SQL hanya saat perlu optimasi berganda.

Untuk kestabilan produksi:

  • Selalu atur timeout Fiber (app.ListenTimeout dan app.ReadTimeout) agar request tidak menggantung saat database lambat.
  • Gunakan konfigurasi environment berbeda (development, staging, production) agar koneksi database tidak tercampur.
  • Tambahkan observability seperti tracing untuk mengetahui latency query GORM.

Debugging GORM bisa dilakukan dengan mengaktifkan logger:

db.Logger = db.Logger.LogMode(logger.Info)

Ini membantu melihat SQL yang dieksekusi beserta waktu eksekusinya.

Penerapan di Fiber

Setelah koneksi siap, injeksikan db *gorm.DB ke handler Fiber lewat dependency injection sederhana atau middleware agar handler tidak membuat koneksi ulang setiap request.

app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
    c.Locals("db", db)
    return c.Next()
})

Dengan pendekatan ini, semua handler dapat memanggil c.Locals("db").(*gorm.DB) untuk menggunakan koneksi yang sama.

Pastikan menutup koneksi SQL saat aplikasi berhenti agar tidak terjadi leak:

defer func() {
    if err := sqlDB.Close(); err != nil {
        log.Printf("Error saat menutup koneksi PG: %v", err)
    }
}()

Penutupan koneksi membantu release resource dan mencegah counter koneksi di database terus meningkat setelah aplikasi restart atau mati.

Kesimpulan

Integrasi GORM dengan Go Fiber v3 mencakup setup modul Go, instalasi dependensi GORM dan driver PostgreSQL, konfigurasi environment, connection pooling, auto ping, dan penanganan error konektivitas. Menggunakan pendekatan ini, aplikasi Fiber siap menerima traffic produksi dengan koneksi database yang sehat, terpantau, dan mudah di-maintain.