Koneksi database sudah siap di part sebelumnya, tapi tabelnya belum ada. Di part ini kita akan buat model Post, migration otomatis lewat GORM, dan seeder untuk mengisi data dummy supaya lebih mudah testing endpoint nanti.
Membuat Model Post
Buat file models/post.go:
package models
import "gorm.io/gorm"
type Post struct {
gorm.Model
Title string `gorm:"size:255;not null" json:"title"`
Slug string `gorm:"size:255;uniqueIndex;not null" json:"slug"`
Body string `gorm:"type:text" json:"body"`
}
Beberapa hal yang perlu diperhatikan:
gorm.Modeladalah struct bawaan GORM yang otomatis menambahkan kolomID,CreatedAt,UpdatedAt, danDeletedAt(untuk soft delete).- Tag
gorm:"..."dipakai untuk mengatur properti kolom di database, seperti panjang (size), constraintnot null, dan index (uniqueIndex). - Tag
json:"..."menentukan bagaimana field ini muncul saat di-encode ke JSON pada response API.
Auto Migration
GORM punya fitur AutoMigrate yang otomatis membuat/menyesuaikan tabel berdasarkan struct model — mirip migration di Laravel, tapi tanpa perlu menulis file migration terpisah untuk kasus sederhana.
Buat file database/migrate.go:
package database
import (
"gorm.io/gorm"
"blogfiber/models"
)
func Migrate(db *gorm.DB) {
db.AutoMigrate(&models.Post{})
}
Panggil Migrate setelah Connect di main.go:
db := database.Connect()
database.Migrate(db)
Setiap kali main.go dijalankan, GORM akan mengecek apakah tabel posts sudah sesuai dengan struct Post. Kalau belum ada, tabel akan dibuat. Kalau sudah ada tapi ada kolom baru di struct, GORM akan menambahkan kolom tersebut (tapi tidak menghapus kolom yang sudah tidak dipakai — itu perlu migration manual).
Membuat Seeder
Untuk data dummy, kita pakai gofakeit:
go get github.com/brianvoe/gofakeit/v6
Karena seeder ini sifatnya dijalankan terpisah dari server utama, kita buat sebagai command sendiri di cmd/seed/main.go:
package main
import (
"fmt"
"log"
"strings"
"github.com/brianvoe/gofakeit/v6"
"github.com/joho/godotenv"
"blogfiber/database"
"blogfiber/models"
)
func main() {
if err := godotenv.Load(); err != nil {
log.Println("tidak menemukan file .env, lanjut pakai environment variable yang ada")
}
db := database.Connect()
database.Migrate(db)
total := 10
for i := 0; i < total; i++ {
title := gofakeit.Sentence(6)
post := models.Post{
Title: title,
Slug: slugify(title),
Body: gofakeit.Paragraph(3, 5, 10, " "),
}
if err := db.Create(&post).Error; err != nil {
log.Fatalf("gagal seed post: %v", err)
}
}
fmt.Printf("berhasil seed %d post\n", total)
}
func slugify(s string) string {
s = strings.ToLower(s)
s = strings.Trim(s, ". ")
s = strings.ReplaceAll(s, " ", "-")
s = strings.ReplaceAll(s, ".", "")
return fmt.Sprintf("%s-%d", s, gofakeit.Number(1000, 9999))
}
Kenapa dipisah jadi command sendiri di cmd/seed/? Supaya seeder tidak ikut jalan setiap kali server API dijalankan — kita panggil manual hanya saat butuh data dummy.
Menjalankan Seeder
go run ./cmd/seed
Kalau berhasil, akan muncul pesan:
berhasil seed 10 post
Kita bisa cek langsung ke database:
SELECT id, title, slug FROM posts LIMIT 5;
Data dummy sudah masuk ke tabel posts. Di part berikutnya kita akan hubungkan handler PostHandler yang sebelumnya masih pakai data statis, supaya benar-benar membaca dan menulis dari database ini.
Bagian dari Series: GoFiber Dasar - Belajar Fundamental Lewat REST API Blog
Belajar konsep-konsep dasar GoFiber (routing, handler, GORM, MySQL, JWT auth) dengan membangun REST API blog sederhana dari nol - lengkap dengan auten...
Lihat Series Lengkap