Membangun Web App E-Commerce dengan Go: #2 - Koneksi Database & Migrasi Skema

Membangun Web App E-Commerce dengan Go: #2 - Koneksi Database & Migrasi Skema

Saatnya menghubungkan aplikasi Go kita ke PostgreSQL! Pelajari cara mengelola koneksi database dengan aman dan membuat tabel pertama menggunakan sistem migrasi.

Penulis: Novian Hidayat
Tanggal: 1 Juli 2025
Level: beginner

Selamat datang kembali di seri tutorial “Membangun Web App E-Commerce dengan Go”! Di bagian pertama, kita telah berhasil menyiapkan lingkungan pengembangan dan menjalankan server web sederhana.

Sekarang, saatnya membuat aplikasi kita lebih berguna dengan menghubungkannya ke database. Di bagian ini, kita akan:

  1. Menginstal driver PostgreSQL untuk Go.
  2. Menyimpan konfigurasi database dengan cara yang aman.
  3. Membuat koneksi dari aplikasi Go ke database PostgreSQL.
  4. Menggunakan sistem migrasi untuk membuat dan mengelola skema database kita secara terstruktur.

Mari kita langsung masuk ke kodenya!

Langkah 1: Instalasi Driver Database pgx

Untuk berkomunikasi dengan PostgreSQL, aplikasi Go kita membutuhkan sebuah “driver”. Salah satu driver yang paling modern, cepat, dan direkomendasikan saat ini adalah pgx.

Buka terminal di direktori root proyek Anda (go-ecommerce) dan jalankan perintah berikut untuk menginstalnya:

go get github.com/jackc/pgx/v5/pgxpool

Perintah go get akan mengunduh paket pgx dan dependensinya, lalu secara otomatis memperbarui file go.mod dan go.sum Anda.

Langkah 2: Konfigurasi Database yang Aman

Menyimpan informasi sensitif seperti password database langsung di dalam kode adalah praktik yang buruk. Kita akan menggunakan file .env untuk menyimpan konfigurasi ini, yang kemudian bisa kita kecualikan dari Git.

Pertama, instal library untuk membaca file .env:

go get github.com/joho/godotenv

Selanjutnya, buat file baru bernama .env di root proyek Anda, dan isi dengan detail koneksi dari file docker-compose.yml kita:

# .env
DATABASE_URL="postgres://admin:secret@localhost:5432/ecommerce_db?sslmode=disable"

Penting: Jangan lupa tambahkan .env ke dalam file .gitignore Anda agar tidak terunggah ke repository. Buat file .gitignore jika belum ada.

# .gitignore
.env

Langkah 3: Membuat Modul Koneksi Database

Kita akan menempatkan logika koneksi database di dalam direktori internal agar terisolasi. Buat folder baru internal/database dan di dalamnya buat file db.go.

mkdir -p internal/database
touch internal/database/db.go

Buka file internal/database/db.go dan tambahkan kode berikut:

// internal/database/db.go
package database

import (
	"context"
	"log"
	"os"

	"github.com/jackc/pgx/v5/pgxpool"
	"github.com/joho/godotenv"
)

func NewConnection() (*pgxpool.Pool, error) {
	// Muat variabel dari file .env
	err := godotenv.Load()
	if err != nil {
		log.Println("Peringatan: Tidak dapat memuat file .env. Menggunakan variabel lingkungan sistem.")
	}

	// Ambil URL database dari environment variable
	databaseURL := os.Getenv("DATABASE_URL")
	if databaseURL == "" {
		log.Fatal("DATABASE_URL tidak diset di environment variable")
	}

	// Buat koneksi pool ke database
	conn, err := pgxpool.New(context.Background(), databaseURL)
	if err != nil {
		return nil, err
	}
    
    // Uji koneksi
    err = conn.Ping(context.Background())
    if err != nil {
        return nil, err
    }

	log.Println("Berhasil terhubung ke database!")
	return conn, nil
}

Penjelasan:

  • Fungsi NewConnection ini akan memuat file .env, mengambil DATABASE_URL, dan membuat sebuah connection pool menggunakan pgxpool.New.
  • Connection pool lebih efisien daripada membuat koneksi baru setiap kali diperlukan.
  • conn.Ping kita gunakan untuk memastikan koneksi benar-benar berhasil sebelum melanjutkan.

Langkah 4: Mengintegrasikan Koneksi ke main.go

Sekarang kita perlu memanggil fungsi NewConnection dari main.go. Modifikasi file cmd/web/main.go Anda menjadi seperti ini:

// cmd/web/main.go
package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/kodekilat/go-ecommerce/internal/database" // Ganti dengan path modul Anda
)

func main() {
    // Membuat koneksi database
	db, err := database.NewConnection()
	if err != nil {
		log.Fatalf("Tidak dapat terhubung ke database: %v", err)
	}
	defer db.Close() // Pastikan koneksi ditutup saat aplikasi berhenti

	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Selamat Datang di Toko Online Go! Koneksi database berhasil.")
	})

	log.Println("Memulai server di http://localhost:8080")

	err = http.ListenAndServe(":8080", mux)
	if err != nil {
		log.Fatal(err)
	}
}

Ganti github.com/kodekilat/go-ecommerce dengan nama modul yang Anda definisikan di go.mod.

Jalankan lagi aplikasi Anda:

go run ./cmd/web/main.go

Di terminal, Anda seharusnya melihat log “Berhasil terhubung ke database!” diikuti oleh “Memulai server…”. Jika ada error, periksa kembali file .env dan pastikan Docker container Anda berjalan.

Langkah 5: Sistem Migrasi dengan golang-migrate

Skema database akan berevolusi seiring waktu. Mengelola perubahan ini secara manual sangat rentan kesalahan. Kita akan menggunakan golang-migrate/migrate, sebuah tool populer untuk menangani migrasi database.

Pertama, instal CLI-nya. Ikuti petunjuk instalasi di halaman rilis resmi.

Setelah terinstal, buat folder untuk menyimpan file-file migrasi kita:

mkdir -p internal/database/migration

Sekarang, gunakan migrate CLI untuk membuat file migrasi pertama kita. File ini akan membuat tabel users.

migrate create -ext sql -dir internal/database/migration -seq create_users_table

Perintah ini akan membuat dua file di dalam folder migration:

  1. ..._create_users_table.up.sql (untuk menerapkan migrasi)
  2. ..._create_users_table.down.sql (untuk membatalkan/rollback migrasi)

Buka file ..._create_users_table.up.sql dan tambahkan skema SQL untuk membuat tabel users:

-- ..._create_users_table.up.sql
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(255),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Kemudian, isi file ..._create_users_table.down.sql untuk menghapus tabelnya:

-- ..._create_users_table.down.sql
DROP TABLE IF EXISTS users;

Terakhir, jalankan migrasi ini ke database kita menggunakan perintah migrate:

migrate -path internal/database/migration -database "postgres://admin:secret@localhost:5432/ecommerce_db?sslmode=disable" -verbose up

Anda akan melihat output yang menandakan migrasi berhasil diterapkan! Anda bisa memeriksa database (misalnya menggunakan DBeaver atau pgAdmin) untuk memastikan tabel users sudah ada.

Penutup

Kerja bagus! Di bagian ini, kita telah menyelesaikan langkah-langkah fundamental untuk manajemen data:

  • Menghubungkan aplikasi Go ke database PostgreSQL.
  • Menerapkan sistem migrasi yang kuat untuk mengelola skema database.

Dengan fondasi ini, kita siap untuk membangun fitur-fitur yang lebih kompleks. Di bagian selanjutnya, kita akan fokus pada pembuatan web server yang lebih terstruktur dengan routing dan rendering template HTML.

Sampai jumpa di bagian ketiga!

Untuk referensi, Anda dapat melihat kode final dari tutorial ini di repositori GitHub berikut: Source code lengkap

Diskusi

Tutorial Lainnya