GORM简介与安装
2026/1/15大约 4 分钟GORMORMGo
GORM 简介与安装
一、GORM 简介
1.1 什么是 GORM
GORM 是 Go 语言的 ORM(Object Relational Mapping)库,提供了完整的数据库操作功能。
核心特性:
- 全功能 ORM
- 关联(Has One、Has Many、Belongs To、Many To Many、多态、单表继承)
- Create、Save、Update、Delete、Find 中钩子方法
- 支持 Preload、Joins 的预加载
- 事务、嵌套事务、Save Point、Rollback To Saved Point
- Context、预编译模式、DryRun 模式
- 批量插入、FindInBatches、Find/Create with Map、使用 SQL 表达式、Context Valuer 进行 CRUD
- SQL 构建器、Upsert、锁、Optimizer/Index/Comment Hint、命名参数、子查询
- 复合主键、索引、约束
- 自动迁移
- 自定义 Logger
- 灵活的可扩展插件 API:Database Resolver(多数据库、读写分离)、Prometheus...
1.2 为什么使用 GORM
1.3 GORM vs 原生 SQL
| 特性 | GORM | 原生 SQL |
|---|---|---|
| 开发效率 | 高 | 低 |
| 类型安全 | 是 | 否 |
| SQL 注入 | 自动防护 | 需手动处理 |
| 关联查询 | 简单 | 复杂 |
| 性能 | 略低 | 高 |
| 灵活性 | 中 | 高 |
二、安装 GORM
2.1 安装核心库
go get -u gorm.io/gorm2.2 安装数据库驱动
# MySQL
go get -u gorm.io/driver/mysql
# PostgreSQL
go get -u gorm.io/driver/postgres
# SQLite
go get -u gorm.io/driver/sqlite
# SQL Server
go get -u gorm.io/driver/sqlserver2.3 版本要求
- Go 1.16+
- GORM v2.0+
三、快速开始
3.1 连接 MySQL
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
// DSN (Data Source Name)
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 {
log.Fatal("连接数据库失败:", err)
}
log.Println("数据库连接成功")
}3.2 定义模型
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"size:100;uniqueIndex"`
Age int `gorm:"default:0"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}3.3 自动迁移
// 自动创建表
db.AutoMigrate(&User{})3.4 CRUD 操作
// 创建
user := User{Name: "张三", Email: "zhangsan@example.com", Age: 25}
db.Create(&user)
// 查询
var result User
db.First(&result, 1) // 根据主键查询
db.First(&result, "name = ?", "张三") // 条件查询
// 更新
db.Model(&result).Update("Age", 26)
db.Model(&result).Updates(User{Name: "李四", Age: 27})
// 删除
db.Delete(&result, 1)四、配置选项
4.1 GORM Config
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
// 跳过默认事务
SkipDefaultTransaction: true,
// 命名策略
NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", // 表名前缀
SingularTable: true, // 使用单数表名
},
// 日志配置
Logger: logger.Default.LogMode(logger.Info),
// 禁用外键约束
DisableForeignKeyConstraintWhenMigrating: true,
// 预编译语句
PrepareStmt: true,
})4.2 连接池配置
sqlDB, err := db.DB()
// 设置最大空闲连接数
sqlDB.SetMaxIdleConns(10)
// 设置最大打开连接数
sqlDB.SetMaxOpenConns(100)
// 设置连接最大生命周期
sqlDB.SetConnMaxLifetime(time.Hour)4.3 日志配置
import (
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags),
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // 日志级别
IgnoreRecordNotFoundError: true, // 忽略 ErrRecordNotFound 错误
Colorful: true, // 彩色打印
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})五、完整示例
5.1 项目结构
myapp/
├── main.go
├── models/
│ └── user.go
├── config/
│ └── database.go
└── go.mod5.2 database.go
package config
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
)
var DB *gorm.DB
func InitDB() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatal("数据库连接失败:", err)
}
// 连接池配置
sqlDB, _ := DB.DB()
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
log.Println("数据库连接成功")
}5.3 user.go
package models
import (
"gorm.io/gorm"
"time"
)
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:100;not null" json:"name"`
Email string `gorm:"size:100;uniqueIndex" json:"email"`
Age int `gorm:"default:0" json:"age"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
// TableName 自定义表名
func (User) TableName() string {
return "users"
}5.4 main.go
package main
import (
"myapp/config"
"myapp/models"
)
func main() {
// 初始化数据库
config.InitDB()
// 自动迁移
config.DB.AutoMigrate(&models.User{})
// 创建用户
user := models.User{
Name: "张三",
Email: "zhangsan@example.com",
Age: 25,
}
config.DB.Create(&user)
// 查询用户
var result models.User
config.DB.First(&result, user.ID)
println("用户名:", result.Name)
}六、常见问题
6.1 连接失败
// 检查 DSN 格式
dsn := "username:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
// 检查数据库是否启动
// 检查防火墙设置
// 检查用户权限6.2 表名问题
// 默认表名是复数形式
type User struct {} // 表名: users
// 使用单数表名
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // 使用单数表名
},
})
// 自定义表名
func (User) TableName() string {
return "my_users"
}6.3 时区问题
// DSN 中指定时区
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
// 或使用 UTC
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=UTC"