Setup project Go + Postgres with Gin and Gorm
Sesi 1: Project Setup + Config + Migrations
Step 1 — Buat Project
Buka terminal, jalankan:
bash mkdir transaction-app cd transaction-app go mod init transaction-app
Step 2 — Install Dependencies
bash go get github.com/gin-gonic/gin go get gorm.io/gorm go get gorm.io/driver/postgres go get github.com/golang-jwt/jwt/v5 go get github.com/joho/godotenv go get golang.org/x/crypto go get github.com/go-playground/validator/v10 go get github.com/google/uuid
Step 3 — Buat Folder Structure
bash mkdir -p cmd mkdir -p internal/config mkdir -p internal/middleware mkdir -p internal/routes mkdir -p internal/domain/auth mkdir -p internal/domain/user mkdir -p internal/domain/role mkdir -p internal/domain/category mkdir -p internal/domain/product mkdir -p internal/domain/transaction mkdir -p internal/domain/detail_transaction mkdir -p internal/domain/invoice mkdir -p internal/domain/payment mkdir -p internal/utils mkdir -p migrations
Step 4 — .env
Buat file .env di root project:
text # App APP_PORT=8080 APP_ENV=development # Database DB_HOST=localhost DB_PORT=5432 DB_USER=postgres DB_PASSWORD=your_password DB_NAME=transaction_db DB_SSLMODE=disable # JWT JWT_SECRET=your_super_secret_key_min_32_chars JWT_EXPIRED_HOURS=24
Buat juga .env.example dengan isi yang sama (value dikosongkan), lalu tambah .gitignore:
text .env *.exe /tmp
Step 5 — internal/config/env.go
go
package config
import (
"log"
"os"
"strconv"
"github.com/joho/godotenv"
)
type AppConfig struct {
AppPort string
AppEnv string
DBHost string
DBPort string
DBUser string
DBPassword string
DBName string
DBSSLMode string
JWTSecret string
JWTExpiredHours int
}
var Config AppConfig
func LoadEnv() {
if err := godotenv.Load(); err != nil {
log.Println("No .env file found, reading from environment variables")
}
expiredHours, err := strconv.Atoi(getEnv("JWT_EXPIRED_HOURS", "24"))
if err != nil {
expiredHours = 24
}
Config = AppConfig{
AppPort: getEnv("APP_PORT", "8080"),
AppEnv: getEnv("APP_ENV", "development"),
DBHost: getEnv("DB_HOST", "localhost"),
DBPort: getEnv("DB_PORT", "5432"),
DBUser: getEnv("DB_USER", "postgres"),
DBPassword: getEnv("DB_PASSWORD", ""),
DBName: getEnv("DB_NAME", "transaction_db"),
DBSSLMode: getEnv("DB_SSLMODE", "disable"),
JWTSecret: getEnv("JWT_SECRET", "secret"),
JWTExpiredHours: expiredHours,
}
}
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
Step 6 — internal/config/database.go
go
package config
import (
"fmt"
"log"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var DB *gorm.DB
func ConnectDB() {
dsn := fmt.Sprintf(
"host=%s port=%s user=%s password=%s dbname=%s sslmode=%s TimeZone=Asia/Jakarta",
Config.DBHost,
Config.DBPort,
Config.DBUser,
Config.DBPassword,
Config.DBName,
Config.DBSSLMode,
)
gormConfig := &gorm.Config{}
if Config.AppEnv == "development" {
gormConfig.Logger = logger.Default.LogMode(logger.Info) // tampilkan query di terminal
}
db, err := gorm.Open(postgres.Open(dsn), gormConfig)
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
sqlDB, err := db.DB()
if err != nil {
log.Fatalf("Failed to get sql.DB: %v", err)
}
// Connection pool settings
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
DB = db
log.Println("Database connected successfully")
}