What it is
GORM is the most widely used ORM for Go, offering associations, hooks, migrations, transactions and eager loading over a struct-based model definition.
Models are plain structs with optional tags. GORM handles CRUD, associations, soft deletes, migrations and transactions, and can log the SQL it generates.
Installation
go get -u gorm.io/gormGetting started
The smallest useful thing you can do with it, and what each part means.
type Book struct {
gorm.Model // ID, CreatedAt, UpdatedAt, DeletedAt
Title string `gorm:"size:200;not null;index"`
AuthorID uint
Author Author
}
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil { return err }
db.AutoMigrate(&Book{}, &Author{})
var books []Book
db.WithContext(ctx).
Where("title LIKE ?", "%Dune%").
Limit(10).
Find(&books)// Without Preload this issues one query per book — the N+1 problem.
var books []Book
db.Preload("Author").Find(&books)
// Nested, and with a condition on the association.
db.Preload("Author.Country").
Preload("Reviews", "rating > ?", 4).
Find(&books)Advanced usage
Where the library earns its place over a simpler alternative.
err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&order).Error; err != nil {
return err // any returned error rolls the whole thing back
}
if err := tx.Model(&Stock{}).
Where("sku = ? AND quantity >= ?", sku, qty).
Update("quantity", gorm.Expr("quantity - ?", qty)).Error; err != nil {
return err
}
return nil
})Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- record not found
- First and Last return gorm.ErrRecordNotFound when nothing matches. Test with errors.Is(err, gorm.ErrRecordNotFound); Find returns an empty slice and no error instead.
- Updates silently skip zero values
- Struct-based Updates ignores zero values such as false, 0 and "". Use a map[string]interface{} or Select the columns explicitly.
Best practices
- Always pass a context with WithContext so queries are cancelled with the request.
- Use Preload for associations you will read — the N+1 problem is GORM's most common performance issue.
- Check .Error on every chain; GORM does not panic on failure, it records the error.
- Enable the logger in development to see the SQL actually being generated.
Background
Why it exists, and what it was reacting to.
Created by Jinzhu, GORM brought a full-featured ORM to a community that had mostly written SQL by hand. Its v2 rewrite in 2020 added context support, prepared-statement caching and a much faster core.
