Go 用 GORM 做 CRUD 实战:模型定义、关联预加载与钩子
test12026-09-261 次阅读
连接数据库与模型定义
GORM 是 Go 里最主流的 ORM,用结构体标签描述表结构,AutoMigrate 可以自动建表或增量加字段。下面用一个用户和订单的场景演示。
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:64;index"`
Email string `gorm:"uniqueIndex"`
CreatedAt time.Time
Orders []Order // 一对多关联
}
type Order struct {
ID uint `gorm:"primaryKey"`
UserID uint `gorm:"index"`
Amount int
Status string `gorm:"default:pending"`
}
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
db.AutoMigrate(&User{}, &Order{})
常规 CRUD
// 创建
u := User{Name: "张三", Email: "z@a.com"}
db.Create(&u)
// 查询
var user User
db.First(&user, u.ID) // 按主键
db.Where("name = ?", "张三").First(&user)
// 更新(只改非零字段)
db.Model(&user).Updates(User{Name: "李四"})
// 删除
db.Delete(&user)
关联预加载
默认查询不会带出关联数据,忘记预加载又在循环里逐条查就会触发 N+1。用 Preload 一次性把关联拉出来。
var users []User
db.Preload("Orders").Find(&users)
for _, u := range users {
fmt.Printf("%s 有 %d 个订单\n", u.Name, len(u.Orders))
}
如果只要已支付的订单,可以传条件:db.Preload("Orders", "status = ?", "paid")。深层关联用点号:Preload("Orders.Items")。
钩子(Hooks)
GORM 在增删改查的各个时点回调特定方法名,适合做密码哈希、默认值、缓存失效等。
func (u *User) BeforeCreate(tx *gorm.DB) error {
if u.Email == "" {
return errors.New("email 不能为空")
}
return nil
}
func (u *User) AfterFind(tx *gorm.DB) error {
// 查出后脱敏,或补一个不在表里的计算字段
return nil
}
工程建议
- 生产环境开启
PrepareStmt提升重复语句性能,并配合连接池。 - 写操作尽量用事务包起来,
db.Transaction(func(tx *gorm.DB) error {...})自动提交或回滚。 - 复杂联表或聚合用
db.Raw/Joins更直观,不必强求全部 ORM 化。
T
test1
文章作者
连接数据库与模型定义 GORM 是 Go 里最主流的 ORM,用结构体标签描述表结构,AutoMigrate 可以自动...
- 分类
- 技术
- 发布时间
- 2026-09-26
- 字数
- 约 1587 字
- 阅读
- 1 次
