GORM: The Go ORM That Actually Respects Your Time
You've been writing Go for a while now, and you've hit that familiar wall: hand-writing SQL queries, manually scanning rows into structs, and writing the same boilerplate CRUD code for every table. It works, but it's tedious. You've probably looked at ORMs in other languages with envy. Enter GORM—the "fantastic ORM library for Golang" that's been around since 2013 and has matured into something genuinely useful for developers who want to move faster without losing control.
What It Does
GORM is a full-featured Object-Relational Mapping library for Go. At its core, it translates between your Go structs and database tables, so you can create, read, update, and delete records without writing SQL by hand. It's built on Go's standard database/sql package, so it works with the databases you're already using.
The feature list reads like a checklist of everything you'd want from an ORM. It handles all the standard associations—Has One, Has Many, Belongs To, Many To Many, plus polymorphism and single-table inheritance. It gives you hooks for lifecycle events like Before/After Create, Save, Update, Delete, and Find. You get eager loading through Preload and Joins, which solves the dreaded N+1 query problem. Transactions are supported, including nested transactions and save points you can roll back to. There's even support for batch inserts and finding records in batches.
Beyond the basics, GORM includes some genuinely thoughtful features: prepared statement mode, dry run mode for testing queries without executing them, composite primary keys, auto migrations, and a flexible plugin API. The project is MIT-licensed and backed by an active contributor community.
Why It's Cool
What makes GORM stand out isn't just the feature count—it's the philosophy baked into the project's description: "developer friendly." That's not marketing fluff; you can see it in the design choices.
-
Everything comes with tests. The README proudly states that every feature has tests. For a library this size, that's a serious commitment to reliability. You're not gambling on a toy project when you build on top of this.
-
The plugin ecosystem is real. GORM doesn't try to do everything itself. The plugin API lets you extend it, and there are already production-grade plugins like Database Resolver (which handles multiple databases and read/write splitting) and Prometheus integration for metrics. You get the core ORM, and you bolt on what you need.
-
It meets you where you are. GORM isn't an all-or-nothing abstraction. You can use its SQL builder for complex queries, drop into raw SQL when you need it, and use features like
NamedArgand SQL expressions in your searches and updates. You're never trapped. -
The polish shows. Context support means you can properly cancel long-running queries. Dry run mode is perfect for debugging—you can see exactly what SQL GORM would generate without executing it. These aren't flashy features, but they're the kind of things that save you hours when something goes wrong.
-
Single-table inheritance and polymorphism. These are advanced features that many ORMs in other languages struggle with. GORM handles them, which means you're not forced into an awkward data model just because your ORM can't represent inheritance.
How to Try It
Getting started with GORM is straightforward. First, grab the library:
go get -u gorm.io/gorm
You'll also need a driver for your database. For example, if you're using SQLite:
go get -u gorm.io/driver/sqlite
Then you can open a connection and start working:
import (
"gorm.io/gorm"
"gorm.io/driver/sqlite"
)
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")
}
// Auto migrate your 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
db.Model(&product).Update("Price", 200)
// Delete
db.Delete(&product)
}
The full guides are available at gorm.io, and there's a separate set of docs for GORM Gen (their code generation tool) at gorm.io/gen. The repository itself is at github.com/go-gorm/gorm, and if you're interested in contributing, they have a page listing ways to help at gorm.io/contribute.html.
Final Thoughts
GORM is one of those libraries that you'll either love immediately or grow to appreciate over time. It's best for developers who want to move fast on CRUD-heavy applications but still need the escape hatch of raw SQL when queries get gnarly. It's not the lightest dependency you'll ever add, but the feature set is genuinely comprehensive, and the plugin architecture means it can grow with you. After a decade of active development, it's proven its staying power. If you're writing Go and you're tired of writing the same SQL boilerplate, give it a shot—you might find yourself wondering why you waited so long.
Follow @githubprojects for more developer tools and open source projects.