← Kembali ke kursus
Pelajaran kursus · Go
Pelajaran 51

SQL

Sambungkan database SQL dengan database/sql.

Pahami konsepnya

Antarmuka database/sql adalah lapisan standar Go untuk database relasional; drivernya dipasang terpisah per database — modernc.org/sqlite untuk SQLite tanpa CGO, go-sql-driver/mysql untuk MySQL, lib/pq untuk Postgres. Driver didaftarkan lewat import dengan efek samping (_ "driver"), lalu sql.Open(namaDriver, sumberData) menyiapkan pool koneksi.

Query mengembalikan baris: rows, err := db.Query(sql) lalu for rows.Next() { rows.Scan(&kolom...) } dan rows.Err() di akhir. QueryRow untuk satu baris, Exec untuk pernyataan tanpa hasil (INSERT/UPDATE/DELETE) yang melaporkan RowsAffected. Parameter selalu placeholder (? atau $1) — NEVER rangkai string SQL, itu pintu injeksi.

db.Ping memverifikasi koneksi nyata (Open malas — baru benar-benar connect saat dipakai). Prepared statement lewat db.Prepare dipakai berulang untuk operasi berparameter dalam jumlah banyak. Konvensi umum: satu objek db dibagi seluruh aplikasi, bukan dibuka-tutup per permintaan.

Coba contoh kode

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "modernc.org/sqlite"
)

func main() {
    db, err := sql.Open("sqlite", "toko.db")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    _, err = db.Exec(`CREATE TABLE IF NOT EXISTS produk (
        id INTEGER PRIMARY KEY, nama TEXT, harga INTEGER)`,
    )
    if err != nil { log.Fatal(err) }

    _, err = db.Exec("INSERT INTO produk (nama, harga) VALUES (?, ?)", "Kopi", 18000)
    if err != nil {
        log.Fatal(err)
    }

    rows, err := db.Query("SELECT id, nama, harga FROM produk")
    if err != nil { log.Fatal(err) }
    defer rows.Close()
    for rows.Next() {
        var id, harga int
        var nama string
        if err := rows.Scan(&id, &nama, &harga); err != nil { log.Fatal(err) }
        fmt.Println(id, nama, harga)
    }
    if err := rows.Err(); err != nil { log.Fatal(err) }
}

Import driver dengan _ karena efeknya pendaftaran, bukan pemakaian langsung. Placeholder ? menjaga nilai tetap data, bukan kode SQL. Loop Query: Next maju per baris, Scan menyalin kolom ke variabel — selalu tutup rows (dan cek rows.Err) agar koneksi kembali ke pool.