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 关键特性
- 模型定义
使用结构体标签定义字段属性
自动处理 CreatedAt、UpdatedAt、DeletedAt
支持主键、索引、唯一约束等
- CRUD 操作
Create:db.Create(&user)
Read:db.First(&user, id)
Update:db.Model(&user).Update(“name”, “new name”)
Delete:db.Delete(&user)
- 查询构建器
链式调用:db.Where().Order().Limit().Find()
预加载关联:db.Preload(“Orders”).Find(&users)
原生 SQL:db.Raw(“SELECT * FROM users”).Scan(&users)
- 关联关系
一对一 :HasOne、BelongsTo
一对多 :HasMany
多对多 :ManyToMany
- 高级特性
事务 :db.Transaction()
钩子 :BeforeSave、AfterCreate 等
作用域 :可重用的查询逻辑
软删除 :自动处理删除标记
- 最佳实践
错误处理 :检查所有数据库操作的错误
连接池 :合理配置数据库连接池参数
迁移管理 :使用自动迁移或迁移工具
性能优化 :使用预加载避免 N+1 查询问题
安全考虑 :使用参数化查询防止 SQL 注入
GORM 提供了强大而灵活的数据库操作能力,是 Go 语言中最流行的 ORM 库,非常适合构建中大型应用程序。
通关密语:gorm