🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 6 Min Lesezeit
0

GORM: Dev's Guide to Go's Most Popular ORM

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

If you're working with Go services that talk to a relational database, chances are you've bumped into GORM. It's the most widely used ORM in the Go ecosystem, and for good reason. It wraps a lot of the tedium of database/sql ,manual scanning, hand-written migrations, string-built queries in a much friendlier API.



This article walks through GORM from setup to the patterns you'll actually use day to day: models, migrations, CRUD, associations, transactions, and a few gotchas that trip people up.






Why reach for an ORM in Go ?



Go's standard database/sql package is deliberately low-level. You write SQL strings, manually scan rows into structs, and manage connections yourself. That's fine for small projects, but it gets repetitive fast once you have a dozen tables and endpoints that all need similar create/read/update/delete logic.



GORM sits on top of database/sql and gives you:




  • Struct-based models mapped to tables

  • Auto migrations

  • A chainable query builder

  • Associations (has-one, has-many, many-to-many, belongs-to)

  • Hooks (before/after create, update, delete)

  • Built-in support for transactions, connection pooling, and prepared statements



It supports PostgreSQL, MySQL, SQLite, SQL Server, and more, through swappable drivers.






Installation






CODE
go get -u gorm.io/gorm
go get -u gorm.io/driver/postgres






Swap postgres for mysql, sqlite, or sqlserver depending on your database.






Connecting to a database






CODE
package main

import (
"log"

"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)

func main() {
dsn := "host=localhost user=postgres password=secret dbname=myapp port=5432 sslmode=disable"

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatalf("failed to connect to database: %v", err)
}

sqlDB, err := db.DB()
if err != nil {
log.Fatalf("failed to get generic db object: %v", err)
}

sqlDB.SetMaxOpenConns(25)
sqlDB.SetMaxIdleConns(10)
}






That db.DB() call gives you the underlying *sql.DB, which is where connection pool settings live. It's easy to forget this step and end up with an ORM that opens far more connections than your database can handle.






Defining models



GORM models are plain structs with tags:




CODE
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;not null"`
Posts []Post
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}

type Post struct {
ID uint `gorm:"primaryKey"`
Title string `gorm:"size:255;not null"`
Body string
UserID uint
}








  • CreatedAt / UpdatedAt are populated automatically by GORM , no extra code needed.


  • DeletedAt gorm.DeletedAt enables soft deletes. Calling db.Delete(&user) won't actually remove the row; it sets deleted_at and every future query filters those rows out automatically.

  • Field-level tags (size, not null, uniqueIndex) get translated into actual SQL constraints during migration.






Auto migrations






CODE
db.AutoMigrate(&User{}, &Post{})






This creates tables if they don't exist and adds missing columns/indexes. It won't drop columns or change types that could cause data loss , which is a deliberate safety choice, but it also means AutoMigrate isn't a full substitute for a proper migration tool once you're in production. Many teams use it for local dev and rely on something like golang-migrate or atlas for production schema changes.






Basic CRUD



Create:




CODE
user := User{Name: "Amina Otieno", Email: "[email protected]"}
result := db.Create(&user)
if result.Error != nil {
log.Println(result.Error)
}
log.Println("New user ID:", user.ID)






Read:




CODE
var user User
db.First(&user, 1)
db.First(&user, "email = ?", "[email protected]")

var users []User
db.Where("name LIKE ?", "%Otieno%").Find(&users)






Update:




CODE
db.Model(&user).Update("name", "Amina O.")

// Update multiple fields
db.Model(&user).Updates(User{Name: "Amina O.", Email: "[email protected]"})






Note: Updates with a struct only updates non-zero fields. If you need to set a field to its zero value (empty string, 0, false), use a map[string]interface{} instead.



Delete:




CODE
db.Delete(&user) 









Associations and preloading



Given the User/Post relationship above, GORM can eager-load associations to avoid N+1 query problems:




CODE
var users []User
db.Preload("Posts").Find(&users)






This runs two queries total (one for users, one for all related posts), rather than one query per user. If you only need a subset of associated records, Preload accepts conditions too:




CODE
db.Preload("Posts", "created_at > ?", someDate).Find(&users)






For many-to-many relationships, GORM manages the join table for you:




CODE
type Tag struct {
ID uint
Name string
Posts []Post `gorm:"many2many:post_tags;"`
}









Transactions






CODE
err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&user).Error; err != nil {
return err // rolls back
}
if err := tx.Create(&Post{Title: "First post", UserID: user.ID}).Error; err != nil {
return err
}
return nil
})
if err != nil {
log.Println("transaction failed:", err)
}






This is the pattern you want anywhere multiple writes need to succeed or fail together — say, deducting a balance and recording a ledger entry.






Hooks



GORM calls certain methods automatically if your model defines them:




CODE
func (u *User) BeforeCreate(tx *gorm.DB) error {
u.Email = strings.ToLower(u.Email)
return nil
}






Available hooks include BeforeCreate, AfterCreate, BeforeUpdate, AfterUpdate, BeforeDelete, AfterDelete, and their *Save equivalents. Useful for normalization, validation, or audit logging without cluttering your handler code.






Things worth knowing





  1. Zero values in updates. As mentioned above, Updates() with a struct silently skips zero-valued fields. This bites people when they try to clear a field to "" or 0.


  2. Soft delete surprises. If DeletedAt is present on a model, every Find/First/Where call filters out soft-deleted rows by default. To include them, use .Unscoped().


  3. N+1 queries. Forgetting Preload on associations is the most common performance issue in GORM codebases. Turn on logger.Info mode in development so you can actually see the queries GORM is generating.


  4. Context propagation. Use db.WithContext(ctx) in request-scoped code so query cancellation and timeouts actually work with your HTTP handler's context.


  5. Connection pool tuning. Don't skip SetMaxOpenConns/SetMaxIdleConns , the defaults aren't tuned for production load.



GORM won't eliminate the need to understand SQL , and you shouldn't want it to , but it removes a lot of boilerplate around scanning rows, building migrations, and wiring up associations. For most Go backend services, especially ones backed by PostgreSQL, it hits a solid balance between productivity and control.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten GORM: Dev's Guide to Go's Most Popular ORM

Thematisch verwandte Begriffe: GORM, Devs, Guide, Most · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...