Go by Example: ORM with GORM
Go 1.23
Simplify database interactions with GORM, a developer-friendly ORM for Go. This example covers defining models, performing auto-migrations, and executing CRUD (Create, Read, Update, Delete) operations with a fluent API.
Code
package main
import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Migrate the schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: "D42", Price: 100})
// Read
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42
// Update - update product's price to 200
db.Model(&product).Update("Price", 200)
// Delete - delete product
db.Delete(&product, 1)
fmt.Println("GORM operations completed")
}Explanation
GORM is a comprehensive Object-Relational Mapping (ORM) library for Go that drastically simplifies database interactions. It abstracts away raw SQL, allowing you to work with Go structs and methods. While powerful, GORM should be used with an understanding of its underlying behavior to avoid performance pitfalls like the "N+1 query problem".
Key Features & Best Practices:
- Model Definition: Embed
gorm.Modelin your structs to automatically include standard fields likeID,CreatedAt,UpdatedAt, andDeletedAt(for soft deletes). - Tags: Use struct tags (e.g.,
gorm:"index;not null;default:'active'") to define schema constraints, indexes, and default values directly in your Go code. - Hooks: Leverage lifecycle hooks such as
BeforeCreateorAfterSaveto automate tasks like password hashing or data validation. - Transactions: Ensure data integrity by wrapping multiple operations in a transaction using
db.Transaction(func(tx *gorm.DB) error { ... }).
Code Breakdown
9
Embedding gorm.Model is a best practice for most tables. It gives you a primary key (ID) and automatic timestamp tracking (CreatedAt, UpdatedAt) without writing boilerplate.
15
gorm.Open initializes the database session. GORM supports multiple drivers (SQLite, MySQL, Postgres). The &gorm.Config{} allows you to customize logging, naming strategies, and more.
21
db.AutoMigrate is a powerful feature that automatically creates or updates database tables to match your Go structs. It is safe to run on startup as it adds missing columns/indexes but won't delete existing data.
24
db.Create accepts a pointer to a struct. It generates the SQL INSERT statement and automatically populates the ID and CreatedAt fields in the struct after insertion.
28
db.First(&product, 1) fetches the first record ordered by primary key. It adds "LIMIT 1" to the SQL query. The second argument is the primary key value.
32
db.Model(&product).Update updates a single column. To update multiple columns, use Updates() with a map or struct. Note that Updates() with a struct will ignore zero values (like 0 or ""), so use a map for those.
35
db.Delete performs a soft delete if the model has a DeletedAt field (which gorm.Model does). The record remains in the DB but is ignored by normal queries. Use Unscoped().Delete() to remove it permanently.

