GORM 是 Go 语言中最流行的 ORM(对象关系映射)框架,它提供了简洁易用的 API,让我们能够用 Go 结构体来操作数据库。本文将详细介绍 GORM 的基础用法。
环境准备#
首先,你需要安装 GORM:
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite提示
本文使用 SQLite 作为演示数据库,因为它无需额外安装即可运行。生产环境请使用 MySQL 或 PostgreSQL。
1. 数据库连接#
1.1 基础连接#
package main
import (
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
log.Fatal("数据库连接失败:", err)
}
log.Println("数据库连接成功!")
}1.2 连接 MySQL#
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{})1.3 连接 PostgreSQL#
dsn := "host=user user=password dbname=dbname port=5432 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})2. 定义模型#
GORM 使用 Go 结构体来定义数据库表模型:
type User struct {
ID uint `gorm:"primaryKey"` // 主键
Name string `gorm:"size:255;not null"` // 姓名
Email string `gorm:"uniqueIndex;size:255"` // 邮箱(唯一索引)
Age int `gorm:"not null"` // 年龄
Birthday *time.Time // 生日(指针类型可为空
CreatedAt time.Time // 创建时间
UpdatedAt time.Time // 更新时间
}常用标签说明#
| 标签 | 说明 |
|---|---|
primaryKey | 设为主键 |
autoIncrement | 自增 |
size:n | 字段大小 |
not null | 非空约束 |
uniqueIndex | 唯一索引 |
index | 普通索引 |
default:value | 默认值 |
foreignKey | 外键 |
3. AutoMigrate 自动迁移#
AutoMigrate 可以自动创建或更新数据库表结构:
// 自动迁移(创建表、添加新字段、删除旧字段)
db.AutoMigrate(&User{})
// 迁移指定表
db.Migrator().CreateTable(&User{})
// 检查表是否存在
db.Migrator().HasTable(&User{})警告
生产环境中谨慎使用 AutoMigrate,它可能会导致数据丢失。建议使用 Migration 文件来管理数据库变更。
4. 增删改查(CRUD)#
4.1 创建记录(Create)#
// 创建单条记录
user := User{Name: "张三", Email: "zhangsan@example.com", Age: 25}
result := db.Create(&user)
fmt.Printf("插入的ID: %d\n", user.ID)
fmt.Printf("影响的行数: %d\n", result.RowsAffected)
// 创建记录并返回错误
if err := db.Create(&user).Error; err != nil {
log.Fatal(err)
}// 批量创建
users := []User{
{Name: "李四", Email: "lisi@example.com", Age: 30},
{Name: "王五", Email: "wangwu@example.com", Age: 28},
{Name: "赵六", Email: "zhaoliu@example.com", Age: 35},
}
db.Create(&users)4.2 查询记录(Read)#
// 根据主键查询
var user User
db.First(&user, 1) // 查询 ID 为 1 的记录
// 条件查询
var user User
db.Where("name = ?", "张三").First(&user)
// 多个条件
db.Where("age > ? AND name LIKE ?", 20, "%张%").Find(&users)
// IN 查询
db.Where("name IN ?", []string{"张三", "李四"}).Find(&users)
// 查询所有记录
var allUsers []User
db.Find(&allUsers)
// 只查询指定字段
db.Select("name, email").Find(&users)
// 排序
db.Order("age DESC, created_at DESC").Find(&users)
// 限制数量
db.Limit(10).Offset(5).Find(&users) // 跳过前5条,取10条4.3 更新记录(Update)#
// 更新单字段
db.Model(&user).Update("name", "新名字")
// 更新多个字段
db.Model(&user).Updates(User{Name: "新名字", Age: 26})
// 使用 Where 更新
db.Where("name = ?", "张三").Model(&User{}).Update("age", 30)
// 更新所有记录
db.Model(&User{}).Where("age < ?", 18).Update("status", "未成年")4.4 删除记录(Delete)#
// 删除单条记录
db.Delete(&user, 1) // 删除 ID 为 1 的记录
// 根据条件删除
db.Where("age < ?", 18).Delete(&User{})
// 软删除(需要包含 DeletedAt 字段)
// db.Delete(&user) // 实际上是将 DeletedAt 设置为当前时间
// 永久删除
db.Unscoped().Delete(&user)5. 完整示例#
以下是一个完整的 CRUD 操作示例:
package main
import (
"fmt"
"log"
"time"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex;size:100"`
Age int `gorm:"not null"`
CreatedAt time.Time
UpdatedAt time.Time
}
// TableName 自定义表名(可选)
func (User) TableName() string {
return "users"
}
func main() {
// 连接数据库
db, err := gorm.Open(sqlite.Open("demo.db"), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// 自动迁移
db.AutoMigrate(&User{})
// ====== Create - 创建 ======
user := User{Name: "张三", Email: "zhangsan@example.com", Age: 25}
db.Create(&user)
fmt.Printf("创建用户,ID: %d\n", user.ID)
// ====== Read - 读取 ======
var foundUser User
db.First(&foundUser, user.ID)
fmt.Printf("查询用户: %s, %s, %d岁\n", foundUser.Name, foundUser.Email, foundUser.Age)
// 条件查询
var users []User
db.Where("age > ?", 20).Find(&users)
fmt.Printf("年龄大于20岁的用户: %d 人\n", len(users))
// ====== Update - 更新 ======
db.Model(&foundUser).Update("age", 26)
fmt.Printf("更新后的年龄: %d\n", foundUser.Age)
// ====== Delete - 删除 ======
db.Delete(&foundUser)
fmt.Println("用户已删除")
}6. 高级查询技巧#
6.1 链式调用#
// 链式调用示例
db.Where("name LIKE ?", "%张%").
Where("age >= ?", 20).
Order("created_at DESC").
Limit(10).
Find(&users)6.2 Scopes 复用查询条件#
func PopularUsers(db *gorm.DB) *gorm.DB {
return db.Where("age > ?", 20).Order("age DESC")
}
func RecentlyRegistered(db *gorm.DB) *gorm.DB {
return db.Where("created_at > ?", time.Now().AddDate(0, -1, 0))
}
// 使用 Scope
db.Scopes(PopularUsers, RecentlyRegistered).Find(&users)6.3 事务操作#
func TransferMoney(db *gorm.DB) error {
return db.Transaction(func(tx *gorm.DB) error {
// 扣除转出账户余额
if err := tx.Model(&Account{}).Where("id = ?", fromID).Update("balance", gorm.Expr("balance - ?", amount)).Error; err != nil {
return err
}
// 增加转入账户余额
if err := tx.Model(&Account{}).Where("id = ?", toID).Update("balance", gorm.Expr("balance + ?", amount)).Error; err != nil {
return err
}
return nil
})
}总结#
本文介绍了 GORM 的核心功能:
- 数据库连接 - 支持 SQLite、MySQL、PostgreSQL 等多种数据库
- 模型定义 - 使用 Go 结构体 + 标签定义数据库表结构
- AutoMigrate - 自动迁移数据库表结构
- CRUD 操作 - 完整的创建、读取、更新、删除 API
- 高级特性 - 链式调用、Scopes、事务等
提示
建议查看 GORM 官方文档 获取更详细的信息和高级用法。

