| name | gorm |
| description | GORM (Go ORM) development assistant. Use when the user needs to: (1) Create GORM models, (2) Define database schemas, (3) Perform CRUD operations, (4) Handle associations and relationships, (5) Write complex queries, (6) Implement migrations, (7) Use hooks and callbacks, (8) Query data, (9) Insert data, (10) Update data, (11) Delete data, (12) Create tables, (13) Modify tables, or any other GORM development tasks. Triggers on phrases like "创建 GORM 模型", "数据库查询", "GORM 关联", "GORM 开发", "查询数据", "写入数据", "更新数据", "删除数据", "创建表", "修改表", "操作数据库", "create GORM model", "database query", "GORM associations", "query data", "insert data", "update data", "delete data", "create table", "modify table". |
GORM 开发指南
GORM 是 Go 语言最流行的 ORM 库,提供完整的数据库操作功能。
⚠️ 重要说明
本 skill 专注于 GORM 的传统 API(Traditional API),不使用泛型方式。
所有示例代码均使用传统的链式调用方式,确保与现有代码和 GORM 插件的完全兼容性。
传统 API vs 泛型 API
var user User
db.Where("name = ?", "John").First(&user)
db.Create(&user)
db.Model(&user).Update("age", 30)
快速开始
安装
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
go get -u gorm.io/driver/postgres
go get -u gorm.io/driver/sqlite
连接数据库
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
}
模型定义
基础模型
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:100"`
Age int `gorm:"default:0"`
Birthday *time.Time
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
使用 gorm.Model
type User struct {
gorm.Model
Name string
Email string
}
字段标签
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null;index"`
Email string `gorm:"uniqueIndex;size:100"`
Age int `gorm:"default:18"`
Active bool `gorm:"default:true"`
Salary float64 `gorm:"type:decimal(10,2)"`
Profile string `gorm:"type:text"`
Extra string `gorm:"-"`
}
CRUD 操作
创建
user := User{Name: "John", Email: "john@example.com", Age: 30}
result := db.Create(&user)
users := []User{
{Name: "John", Email: "john@example.com"},
{Name: "Jane", Email: "jane@example.com"},
}
db.Create(&users)
db.Model(&User{}).Create(map[string]interface{}{
"Name": "John",
"Age": 30,
})
查询
var user User
db.First(&user)
db.Last(&user)
db.First(&user, 10)
var users []User
db.Find(&users)
db.Where("name = ?", "John").First(&user)
db.Where("name = ? AND age >= ?", "John", 20).Find(&users)
db.Where("name IN ?", []string{"John", "Jane"}).Find(&users)
db.Where("name LIKE ?", "%john%").Find(&users)
db.Where(&User{Name: "John", Age: 20}).First(&user)
db.Where(map[string]interface{}{"name": "John", "age": 20}).Find(&users)
db.Not("name = ?", "John").Find(&users)
db.Where("name = ?", "John").Or("name = ?", "Jane").Find(&users)
db.Select("name", "age").Find(&users)
db.Order("age desc, name").Find(&users)
db.Limit(10).Offset(5).Find(&users)
db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("total > ?", 100).Find(&results)
更新
db.Model(&user).Update("name", "John Doe")
db.Model(&user).Updates(User{Name: "John", Age: 30})
db.Model(&user).Updates(map[string]interface{}{"name": "John", "age": 30})
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "John", "age": 30})
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
db.Model(&User{}).Update("age", gorm.Expr("age + ?", 1))
删除
db.Delete(&user)
db.Delete(&User{}, 10)
db.Delete(&User{}, []int{1, 2, 3})
db.Where("name = ?", "John").Delete(&User{})
db.Delete(&user)
db.Unscoped().Delete(&user)
db.Unscoped().Where("age = ?", 20).Find(&users)
关联关系
Belongs To
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
gorm.Model
Name string
}
db.Preload("Company").Find(&users)
Has One
type User struct {
gorm.Model
Name string
Profile Profile
}
type Profile struct {
gorm.Model
UserID uint
Bio string
}
db.Preload("Profile").Find(&users)
Has Many
type User struct {
gorm.Model
Name string
Orders []Order
}
type Order struct {
gorm.Model
UserID uint
Amount float64
}
db.Preload("Orders").Find(&users)
Many To Many
type User struct {
gorm.Model
Name string
Roles []Role `gorm:"many2many:user_roles;"`
}
type Role struct {
gorm.Model
Name string
Users []User `gorm:"many2many:user_roles;"`
}
db.Preload("Roles").Find(&users)
db.Model(&user).Association("Roles").Append(&role)
db.Model(&user).Association("Roles").Delete(&role)
db.Model(&user).Association("Roles").Clear()
高级查询
子查询
db.Where("amount > (?)", db.Table("orders").Select("AVG(amount)")).Find(&orders)
原生 SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "John").Scan(&result)
db.Exec("UPDATE users SET age = ? WHERE name = ?", 30, "John")
事务
db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&user).Error; err != nil {
return err
}
if err := tx.Create(&order).Error; err != nil {
return err
}
return nil
})
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Create(&user).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Create(&order).Error; err != nil {
tx.Rollback()
return err
}
tx.Commit()
Hooks
func (u *User) BeforeCreate(tx *gorm.DB) error {
u.UUID = uuid.New()
return nil
}
func (u *User) AfterCreate(tx *gorm.DB) error {
return nil
}
func (u *User) BeforeUpdate(tx *gorm.DB) error {
return nil
}
func (u *User) AfterUpdate(tx *gorm.DB) error {
return nil
}
func (u *User) BeforeDelete(tx *gorm.DB) error {
return nil
}
func (u *User) AfterDelete(tx *gorm.DB) error {
return nil
}
func (u *User) AfterFind(tx *gorm.DB) error {
return nil
}
迁移
db.AutoMigrate(&User{}, &Order{}, &Company{})
db.Migrator().HasTable(&User{})
db.Migrator().CreateTable(&User{})
db.Migrator().DropTable(&User{})
db.Migrator().RenameTable(&User{}, &UserInfo{})
db.Migrator().AddColumn(&User{}, "Age")
db.Migrator().DropColumn(&User{}, "Age")
db.Migrator().AlterColumn(&User{}, "Age")
db.Migrator().CreateIndex(&User{}, "Email")
db.Migrator().DropIndex(&User{}, "Email")
最佳实践
- 使用连接池:配置合适的连接池参数
- 预加载关联:避免 N+1 查询问题
- 使用事务:保证数据一致性
- 软删除:使用 DeletedAt 字段
- 索引优化:为常用查询字段添加索引
- 批量操作:使用批量插入/更新提升性能
- 错误处理:始终检查 Error 返回值
- 使用 Context:支持超时和取消操作
官方文档参考
详细文档请参考 references/ 目录下的官方文档。