GORM Setup for Go Web Application
GORM is the most popular ORM for Go. It doesn't try to hide SQL completely, giving direct access to raw queries where needed. Version v2 is incompatible with v1 API-wise.
go get gorm.io/gorm
go get gorm.io/driver/postgres
Initialization
package db
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"time"
)
func New(dsn string) (*gorm.DB, error) {
db, err := gorm.Open(postgres.New(postgres.Config{
DSN: dsn,
PreferSimpleProtocol: true,
}), &gorm.Config{
Logger: logger.Default.LogMode(logger.Warn),
NowFunc: func() time.Time { return time.Now().UTC() },
})
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(5 * time.Minute)
return db, err
}
Models
type Product struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Title string `gorm:"type:varchar(500);not null"`
Slug string `gorm:"type:varchar(520);uniqueIndex"`
Price float64 `gorm:"type:decimal(12,2)"`
Status ProductStatus `gorm:"type:varchar(20);default:draft"`
CategoryID uint `gorm:"not null;index"`
Category Category `gorm:"foreignKey:CategoryID;constraint:OnDelete:RESTRICT"`
Tags []Tag `gorm:"many2many:product_tags;"`
}
func (Product) TableName() string {
return "products"
}
Queries
type ProductRepository struct {
db *gorm.DB
}
func (r *ProductRepository) GetPublished(
ctx context.Context,
categoryID uint,
limit, offset int,
) ([]Product, error) {
var products []Product
err := r.db.WithContext(ctx).
Preload("Category").
Preload("Tags").
Where("category_id = ? AND status = ?", categoryID, "published").
Order("created_at DESC").
Limit(limit).
Offset(offset).
Find(&products).Error
return products, err
}
Migrations
Use golang-migrate for production:
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
migrate create -ext sql -dir migrations -seq create_products
Timeline
Initial GORM setup with golang-migrate: 1 day.







