2. GORM 快速入门:安装、配置、模型与 CRUD
本章是 GORM 的实战起点。你将学会如何安装 GORM、配置数据库连接、定义模型、使用 AutoMigrate 自动建表,并完成最核心的 CRUD 操作。掌握这些基础后,后续的迁移与性能剖析才有坚实的操作基础。
2.1 GORM 安装与数据库驱动
GORM 采用模块化驱动设计,安装时需同时选择对应的数据库驱动。以下为常用驱动组合:
| 数据库 | 驱动包路径 | 导入别名 |
|---|---|---|
| MySQL | gorm.io/driver/mysql |
"gorm.io/driver/mysql" |
| PostgreSQL | gorm.io/driver/postgres |
"gorm.io/driver/postgres" |
| SQLite | gorm.io/driver/sqlite |
"gorm.io/driver/sqlite" |
| SQL Server | gorm.io/driver/sqlserver |
"gorm.io/driver/sqlserver" |
安装命令(以 MySQL 为例):
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
2.2 数据库连接配置
GORM 通过 gorm.Open 建立连接,支持 DSN 字符串与配置结构体两种方式。推荐使用配置结构体,便于后期扩展连接池参数。
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// DSN 格式:user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true, // 关闭默认事务提升性能
PrepareStmt: true, // 缓存预编译语句
})
if err != nil {
panic("数据库连接失败: " + err.Error())
}
// 获取底层 sql.DB 实例,配置连接池
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
sqlDB.SetConnMaxLifetime(time.Hour)
连接池参数建议: 生产环境
SetMaxOpenConns 建议不超过数据库最大连接数的 80%,SetConnMaxLifetime 建议小于数据库的 wait_timeout(通常 300s)。
2.3 模型定义基础
GORM 模型是 Go 结构体,通过标签(Tag)映射数据库表字段。推荐内嵌 gorm.Model 自动获得 ID、CreatedAt、UpdatedAt、DeletedAt 四个通用字段。
type User struct {
gorm.Model // 内嵌:ID, CreatedAt, UpdatedAt, DeletedAt
Name string `gorm:"type:varchar(100);not null;comment:用户名"`
Email string `gorm:"type:varchar(200);uniqueIndex;comment:邮箱"`
Age uint8 `gorm:"default:18;comment:年龄"`
Birthday *time.Time `gorm:"comment:生日"`
MemberNumber sql.NullString `gorm:"uniqueIndex;comment:会员号"`
Status int `gorm:"default:1;comment:状态 1-启用 0-禁用"`
}
| 标签 | 作用 | 示例 |
|---|---|---|
column |
指定列名 | column:user_name |
type |
列数据类型 | type:varchar(100) |
size |
列大小/长度 | size:256 |
primaryKey |
主键 | primaryKey |
uniqueIndex |
唯一索引 | uniqueIndex |
default |
默认值 | default:18 |
not null |
非空约束 | not null |
comment |
字段注释 | comment:用户名 |
2.4 AutoMigrate 自动迁移
AutoMigrate 会根据模型结构体自动创建或更新数据库表,仅会新增列、修改列类型、增加索引,不会删除列或索引,适合开发与测试环境快速迭代。
// 自动迁移:创建或更新表结构
err := db.AutoMigrate(&User{}, &Product{}, &Order{})
if err != nil {
panic("自动迁移失败: " + err.Error())
}
生产环境注意: AutoMigrate 不会处理列重命名、列删除、数据迁移等破坏性变更。生产环境应使用版本化迁移工具(如 golang-migrate)或 GORM 的 Migrator 接口手动控制。
2.5 CRUD 基本操作
GORM 的 CRUD 方法链式调用,语义清晰。以下为最常用的操作模式:
2.5.1 创建(Create)
// 单条创建
user := User{Name: "张三", Email: "zhangsan@example.com", Age: 25}
result := db.Create(&user)
fmt.Println("新记录 ID:", user.ID, "影响行数:", result.RowsAffected)
// 批量创建
users := []User{
{Name: "李四", Email: "lisi@example.com"},
{Name: "王五", Email: "wangwu@example.com"},
}
db.Create(&users)
2.5.2 查询(Read)
// 查询单条
var user User
db.First(&user, 1) // 按主键查询
db.First(&user, "email = ?", "zhangsan@example.com") // 条件查询
// 查询多条
var users []User
db.Where("age > ?", 20).Find(&users) // 条件过滤
db.Limit(10).Offset(0).Find(&users) // 分页查询
// 查询特定字段
db.Select("name", "email").Find(&users)
2.5.3 更新(Update)
// 更新单个字段
db.Model(&User{}).Where("id = ?", 1).Update("name", "张三丰")
// 更新多个字段
db.Model(&user).Updates(User{Name: "张三丰", Age: 30}) // 零值字段不会被更新
db.Model(&user).Updates(map[string]interface{}{"name": "张三丰", "age": 30}) // 零值也会更新
2.5.4 删除(Delete)
// 软删除(模型内嵌 gorm.Model 时默认软删除)
db.Delete(&User{}, 1)
// 物理删除
db.Unscoped().Delete(&User{}, 1)
CRUD 避坑指南:
- Updates 零值问题: 结构体更新时零值字段不会被更新,如需更新零值请使用
map。 - First 与 Take 区别:
First按主键排序取第一条,Take不排序直接取一条。 - 软删除查询: 默认查询会过滤
deleted_at IS NULL的记录,使用Unscoped()可查询全部。
2.6 完整示例:用户表 CRUD
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string `gorm:"type:varchar(100);not null"`
Email string `gorm:"type:varchar(200);uniqueIndex;not null"`
Age uint8 `gorm:"default:18"`
}
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("连接失败")
}
// 自动迁移
db.AutoMigrate(&User{})
// 创建
db.Create(&User{Name: "张三", Email: "zs@example.com", Age: 25})
// 查询
var user User
db.First(&user, "email = ?", "zs@example.com")
fmt.Printf("查询结果: %+v\n", user)
// 更新
db.Model(&user).Update("age", 26)
// 删除
db.Delete(&user)
}
通过以上步骤,你已经完成了 GORM 的安装、数据库连接、模型定义、自动迁移以及完整的 CRUD 操作。这些基础能力将贯穿后续所有章节,请务必动手实践每个代码片段。