Go Gorm

GORM 是 Go 语言中最流行的 ORM(对象关系映射)库,提供了强大的数据库操作功能,支持多种数据库(MySQL、PostgreSQL、SQLite、SQL Server 等)。

下面是一个示例:

package main

import (
    "fmt"
    "log"
    "os"
    "time"

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

// 1. 基本模型定义
type User struct {
    ID        uint      `gorm:"primaryKey" json:"id"`
    Name      string    `gorm:"size:100;not null" json:"name"`
    Email     string    `gorm:"uniqueIndex;size:255" json:"email"`
    Age       int       `gorm:"default:18" json:"age"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

// 2. 产品模型
type Product struct {
    ID          uint      `gorm:"primaryKey" json:"id"`
    Name        string    `gorm:"size:255;not null" json:"name"`
    Price       float64   `gorm:"type:decimal(10,2)" json:"price"`
    Description string    `gorm:"type:text" json:"description"`
    Stock       int       `gorm:"default:0" json:"stock"`
    IsActive    bool      `gorm:"default:true" json:"is_active"`
    CreatedAt   time.Time `json:"created_at"`
    UpdatedAt   time.Time `json:"updated_at"`
}

// 3. 订单模型
type Order struct {
    ID        uint      `gorm:"primaryKey" json:"id"`
    UserID    uint      `json:"user_id"`
    User      User      `gorm:"foreignKey:UserID" json:"user"`
    Amount    float64   `gorm:"type:decimal(10,2)" json:"amount"`
    Status    string    `gorm:"size:50;default:pending" json:"status"`
    CreatedAt time.Time `json:"created_at"`
}

// 4. 订单项模型
type OrderItem struct {
    ID        uint    `gorm:"primaryKey" json:"id"`
    OrderID   uint    `json:"order_id"`
    Order     Order   `gorm:"foreignKey:OrderID" json:"order"`
    ProductID uint    `json:"product_id"`
    Product   Product `gorm:"foreignKey:ProductID" json:"product"`
    Quantity  int     `gorm:"default:1" json:"quantity"`
    Price     float64 `gorm:"type:decimal(10,2)" json:"price"`
}

// 数据库连接管理
type Database struct {
    *gorm.DB
}

func NewDatabase() (*Database, error) {
    // 配置 GORM 日志
    newLogger := logger.New(
        log.New(os.Stdout, "\r\n", log.LstdFlags),
        logger.Config{
            SlowThreshold: time.Second,
            LogLevel:      logger.Info,
            Colorful:      true,
        },
    )

    // 连接 SQLite 数据库(生产环境建议使用 MySQL/PostgreSQL)
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
        Logger: newLogger,
    })
    if err != nil {
        return nil, fmt.Errorf("连接数据库失败: %v", err)
    }

    return &Database{db}, nil
}

func (db *Database) Close() error {
    sqlDB, err := db.DB.DB()
    if err != nil {
        return err
    }
    return sqlDB.Close()
}

func (db *Database) AutoMigrate() error {
    // 自动迁移表结构
    err := db.AutoMigrate(
        &User{},
        &Product{},
        &Order{},
        &OrderItem{},
    )
    if err != nil {
        return fmt.Errorf("自动迁移失败: %v", err)
    }
    fmt.Println("✅ 数据库表结构迁移完成")
    return nil
}

// 基本 CRUD 操作示例
func demonstrateBasicCRUD(db *Database) {
    fmt.Println("\n=== 基本 CRUD 操作 ===")

    // 创建用户
    fmt.Println("\n1. 创建用户:")
    users := []User{
        {Name: "张三", Email: "zhang@example.com", Age: 25},
        {Name: "李四", Email: "li@example.com", Age: 30},
        {Name: "王五", Email: "wang@example.com", Age: 28},
    }

    result := db.Create(&users)
    if result.Error != nil {
        log.Printf("创建用户失败: %v", result.Error)
        return
    }
    fmt.Printf("创建了 %d 个用户\n", result.RowsAffected)

    // 查询用户
    fmt.Println("\n2. 查询用户:")
    var foundUser User
    db.First(&foundUser, "email = ?", "zhang@example.com")
    fmt.Printf("查询结果: %s (%s), 年龄: %d\n", foundUser.Name, foundUser.Email, foundUser.Age)

    // 查询所有用户
    var allUsers []User
    db.Find(&allUsers)
    fmt.Println("所有用户:")
    for _, user := range allUsers {
        fmt.Printf("  - ID: %d, 姓名: %s, 邮箱: %s\n", user.ID, user.Name, user.Email)
    }

    // 更新用户
    fmt.Println("\n3. 更新用户:")
    db.Model(&foundUser).Update("Age", 26)
    fmt.Printf("更新用户年龄: %s 现在 %d 岁\n", foundUser.Name, 26)

    // 条件更新
    db.Model(&User{}).Where("age < ?", 30).Update("Age", gorm.Expr("age + ?", 1))
    fmt.Println("年龄小于30的用户年龄加1")

    // 删除用户
    fmt.Println("\n4. 删除用户:")
    var userToDelete User
    db.First(&userToDelete, "email = ?", "wang@example.com")
    db.Delete(&userToDelete)
    fmt.Printf("删除用户: %s\n", userToDelete.Name)
}

// 产品管理示例
func demonstrateProductManagement(db *Database) {
    fmt.Println("\n=== 产品管理 ===")

    // 创建产品
    fmt.Println("\n1. 创建产品:")
    products := []Product{
        {Name: "MacBook Pro", Price: 12999.99, Description: "苹果笔记本电脑", Stock: 50},
        {Name: "iPhone 14", Price: 5999.99, Description: "苹果手机", Stock: 100},
        {Name: "iPad Air", Price: 4399.99, Description: "苹果平板电脑", Stock: 30},
        {Name: "AirPods", Price: 1299.99, Description: "无线耳机", Stock: 200},
    }

    db.Create(&products)
    fmt.Println("创建了4个产品")

    // 查询和过滤
    fmt.Println("\n2. 查询和过滤:")

    // 查询价格大于5000的产品
    var expensiveProducts []Product
    db.Where("price > ?", 5000).Find(&expensiveProducts)
    fmt.Println("价格大于5000的产品:")
    for _, p := range expensiveProducts {
        fmt.Printf("  - %s: ¥%.2f\n", p.Name, p.Price)
    }

    // 查询库存少于100的产品并按价格排序
    var lowStockProducts []Product
    db.Where("stock < ?", 100).Order("price desc").Find(&lowStockProducts)
    fmt.Println("库存少于100的产品(按价格降序):")
    for _, p := range lowStockProducts {
        fmt.Printf("  - %s: ¥%.2f (库存: %d)\n", p.Name, p.Price, p.Stock)
    }

    // 分页查询
    fmt.Println("\n3. 分页查询:")
    var pageProducts []Product
    db.Limit(2).Offset(0).Find(&pageProducts)
    fmt.Println("第1页(每页2条):")
    for _, p := range pageProducts {
        fmt.Printf("  - %s: ¥%.2f\n", p.Name, p.Stock)
    }

    // 统计
    fmt.Println("\n4. 统计查询:")
    var totalProducts int64
    var avgPrice float64
    db.Model(&Product{}).Count(&totalProducts)
    db.Model(&Product{}).Select("AVG(price)").Row().Scan(&avgPrice)
    fmt.Printf("产品总数: %d, 平均价格: ¥%.2f\n", totalProducts, avgPrice)
}

// 关联操作示例
func demonstrateAssociations(db *Database) {
    fmt.Println("\n=== 关联操作 ===")

    // 创建订单和订单项
    fmt.Println("\n1. 创建订单:")

    // 获取用户和产品
    var user User
    var products []Product
    db.First(&user)
    db.Limit(2).Find(&products)

    // 创建订单
    order := Order{
        UserID: user.ID,
        Amount: products[0].Price*2 + products[1].Price,
        Status: "pending",
    }
    db.Create(&order)

    // 创建订单项
    orderItems := []OrderItem{
        {OrderID: order.ID, ProductID: products[0].ID, Quantity: 2, Price: products[0].Price},
        {OrderID: order.ID, ProductID: products[1].ID, Quantity: 1, Price: products[1].Price},
    }
    db.Create(&orderItems)

    fmt.Printf("创建订单成功,订单金额: ¥%.2f\n", order.Amount)

    // 预加载关联数据
    fmt.Println("\n2. 预加载关联数据:")
    var orderWithDetails Order
    db.Preload("User").Preload("OrderItems.Product").First(&orderWithDetails, order.ID)

    fmt.Printf("订单详情:\n")
    fmt.Printf("  用户: %s\n", orderWithDetails.User.Name)
    fmt.Printf("  状态: %s\n", orderWithDetails.Status)
    fmt.Printf("  金额: ¥%.2f\n", orderWithDetails.Amount)
    fmt.Printf("  商品:\n")
    for _, item := range orderWithDetails.OrderItems {
        fmt.Printf("    - %s: %d × ¥%.2f\n", item.Product.Name, item.Quantity, item.Price)
    }

    // 关联查询
    fmt.Println("\n3. 关联查询:")
    var ordersWithUsers []Order
    db.Joins("User").Where("User.age > ?", 25).Find(&ordersWithUsers)
    fmt.Println("年龄大于25的用户的订单:")
    for _, o := range ordersWithUsers {
        fmt.Printf("  - 订单%d: %s, 金额: ¥%.2f\n", o.ID, o.User.Name, o.Amount)
    }
}

// 事务操作示例
func demonstrateTransactions(db *Database) {
    fmt.Println("\n=== 事务操作 ===")

    // 开始事务
    err := db.Transaction(func(tx *gorm.DB) error {
        // 创建用户
        newUser := User{Name: "事务用户", Email: "transaction@example.com", Age: 35}
        if err := tx.Create(&newUser).Error; err != nil {
            return err
        }

        // 创建产品
        newProduct := Product{Name: "事务产品", Price: 999.99, Stock: 10}
        if err := tx.Create(&newProduct).Error; err != nil {
            return err
        }

        // 创建订单
        order := Order{
            UserID: newUser.ID,
            Amount: newProduct.Price * 3,
            Status: "completed",
        }
        if err := tx.Create(&order).Error; err != nil {
            return err
        }

        // 创建订单项
        orderItem := OrderItem{
            OrderID:   order.ID,
            ProductID: newProduct.ID,
            Quantity:  3,
            Price:     newProduct.Price,
        }
        if err := tx.Create(&orderItem).Error; err != nil {
            return err
        }

        fmt.Println("✅ 事务操作成功完成")
        return nil
    })

    if err != nil {
        fmt.Printf("❌ 事务操作失败: %v\n", err)
    }
}

// 钩子函数示例
type AuditLog struct {
    ID        uint      `gorm:"primaryKey"`
    TableName string    `gorm:"size:100"`
    RecordID  uint      `gorm:"not null"`
    Action    string    `gorm:"size:50"`
    OldData   string    `gorm:"type:text"`
    NewData    string    `gorm:"type:text"`
    CreatedAt time.Time `gorm:"not null"`
}

// 为 User 模型添加钩子
func (u *User) BeforeCreate(tx *gorm.DB) error {
    fmt.Printf("🎯 准备创建用户: %s\n", u.Name)
    return nil
}

func (u *User) AfterCreate(tx *gorm.DB) error {
    fmt.Printf("✅ 用户创建完成: %s (ID: %d)\n", u.Name, u.ID)

    // 记录审计日志
    auditLog := AuditLog{
        TableName: "users",
        RecordID:  u.ID,
        Action:    "create",
        NewData:   fmt.Sprintf("Name: %s, Email: %s", u.Name, u.Email),
        CreatedAt: time.Now(),
    }
    tx.Create(&auditLog)

    return nil
}

func (u *User) BeforeUpdate(tx *gorm.DB) error {
    fmt.Printf("🎯 准备更新用户: %s\n", u.Name)
    return nil
}

func demonstrateHooks(db *Database) {
    fmt.Println("\n=== 钩子函数示例 ===")

    // 创建审计日志表
    db.AutoMigrate(&AuditLog{})

    // 创建带钩子的用户
    hookUser := User{
        Name:  "钩子用户",
        Email: "hook@example.com",
        Age:   40,
    }
    db.Create(&hookUser)

    // 更新用户触发更新钩子
    db.Model(&hookUser).Update("Age", 41)
}

// 复杂查询示例
func demonstrateComplexQueries(db *Database) {
    fmt.Println("\n=== 复杂查询示例 ===")

    // 原生 SQL 查询
    fmt.Println("\n1. 原生 SQL 查询:")
    type ProductStats struct {
        Name  string  `json:"name"`
        Total float64 `json:"total"`
        Count int     `json:"count"`
    }

    var stats []ProductStats
    db.Raw(`
        SELECT p.name,
               SUM(oi.quantity * oi.price) as total,
               COUNT(oi.id) as count
        FROM order_items oi
        JOIN products p ON oi.product_id = p.id
        GROUP BY p.id, p.name
        HAVING total > ?
        ORDER BY total DESC
    `, 1000).Scan(&stats)

    fmt.Println("产品销售统计:")
    for _, s := range stats {
        fmt.Printf("  - %s: 销售额 ¥%.2f (订单数: %d)\n", s.Name, s.Total, s.Count)
    }

    // 子查询
    fmt.Println("\n2. 子查询:")
    var expensiveUsers []User
    db.Where("id IN (?)",
        db.Table("orders").Select("DISTINCT user_id").Where("amount > ?", 1000),
    ).Find(&expensiveUsers)

    fmt.Println("消费金额大于1000的用户:")
    for _, u := range expensiveUsers {
        fmt.Printf("  - %s (%s)\n", u.Name, u.Email)
    }

    // 选择特定字段
    fmt.Println("\n3. 选择字段:")
    type UserInfo struct {
        Name  string `json:"name"`
        Email string `json:"email"`
    }
    var userInfos []UserInfo
    db.Model(&User{}).Select("name, email").Find(&userInfos)
    fmt.Println("用户基本信息:")
    for _, info := range userInfos {
        fmt.Printf("  - %s (%s)\n", info.Name, info.Email)
    }
}

// 软删除示例
type SoftDeleteModel struct {
    ID        uint           `gorm:"primaryKey"`
    Name      string         `gorm:"size:100"`
    DeletedAt gorm.DeletedAt `gorm:"index"` // 软删除字段
}

func demonstrateSoftDelete(db *Database) {
    fmt.Println("\n=== 软删除示例 ===")

    // 创建软删除表
    db.AutoMigrate(&SoftDeleteModel{})

    // 创建测试数据
    softItem := SoftDeleteModel{Name: "软删除测试"}
    db.Create(&softItem)

    // 软删除
    db.Delete(&softItem)
    fmt.Printf("软删除项目: %s\n", softItem.Name)

    // 查询(不包括已删除的)
    var activeItems []SoftDeleteModel
    db.Find(&activeItems)
    fmt.Printf("软删除后剩余项目数: %d\n", len(activeItems))

    // 查询包括已删除的
    var allItems []SoftDeleteModel
    db.Unscoped().Find(&allItems)
    fmt.Printf("包括已删除的项目数: %d\n", len(allItems))

    // 永久删除
    db.Unscoped().Delete(&softItem)
    fmt.Println("永久删除完成")
}

// 数据库连接池配置
func configureConnectionPool(db *Database) {
    sqlDB, err := db.DB.DB()
    if err != nil {
        log.Fatal(err)
    }

    // 设置连接池参数
    sqlDB.SetMaxIdleConns(10)           // 最大空闲连接数
    sqlDB.SetMaxOpenConns(100)         // 最大打开连接数
    sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大存活时间

    fmt.Println("✅ 数据库连接池配置完成")
}

func main() {
    // 初始化数据库
    database, err := NewDatabase()
    if err != nil {
        log.Fatal(err)
    }
    defer database.Close()

    // 配置连接池
    configureConnectionPool(database)

    // 自动迁移表结构
    if err := database.AutoMigrate(); err != nil {
        log.Fatal(err)
    }

    // 清空测试数据(可选)
    database.Exec("DELETE FROM users")
    database.Exec("DELETE FROM products")
    database.Exec("DELETE FROM orders")
    database.Exec("DELETE FROM order_items")

    // 运行各种示例
    demonstrateBasicCRUD(database)
    demonstrateProductManagement(database)
    demonstrateAssociations(database)
    demonstrateTransactions(database)
    demonstrateHooks(database)
    demonstrateComplexQueries(database)
    demonstrateSoftDelete(database)

    fmt.Println("\n🎉 所有示例执行完成!")
}

GORM 关键特性

  1. ​ 模型定义 ​

使用结构体标签定义字段属性

自动处理 CreatedAt、UpdatedAt、DeletedAt

支持主键、索引、唯一约束等

  1. ​CRUD 操作 ​

​Create​:db.Create(&user)

​Read​:db.First(&user, id)

​Update​:db.Model(&user).Update(“name”, “new name”)

​Delete​:db.Delete(&user)

  1. ​ 查询构建器 ​

链式调用:db.Where().Order().Limit().Find()

预加载关联:db.Preload(“Orders”).Find(&users)

原生 SQL:db.Raw(“SELECT * FROM users”).Scan(&users)

  1. ​ 关联关系 ​

​ 一对一 ​:HasOne、BelongsTo

​ 一对多 ​:HasMany

​ 多对多 ​:ManyToMany

  1. ​ 高级特性 ​

​ 事务 ​:db.Transaction()

​ 钩子 ​:BeforeSave、AfterCreate 等

​ 作用域 ​:可重用的查询逻辑

​ 软删除 ​:自动处理删除标记

  1. ​ 最佳实践 ​

​ 错误处理 ​:检查所有数据库操作的错误

​ 连接池 ​:合理配置数据库连接池参数

​ 迁移管理 ​:使用自动迁移或迁移工具

​ 性能优化 ​:使用预加载避免 N+1 查询问题

​ 安全考虑 ​:使用参数化查询防止 SQL 注入

GORM 提供了强大而灵活的数据库操作能力,是 Go 语言中最流行的 ORM 库,非常适合构建中大型应用程序。

通关密语:gorm