Skip to content
Go
安装与快速开始

安装与快速开始

GORM 是 Go 语言中最流行的 ORM 框架,提供全功能的对象关系映射。它内置了 CRUD 操作、关联关系、事务、钩子、迁移等能力,同时保留原生 SQL 的灵活性。

官网文档:GORM Guides GitHub:go-gorm/gorm


前置条件

  • Go 版本:GORM v2 需要 Go 1.14 或更高版本(推荐 Go 1.18+)
  • 数据库驱动:GORM 本身不包含数据库驱动,需额外安装对应驱动(见下文)

安装

# 安装 GORM 核心库
go get -u gorm.io/gorm

# 按需安装数据库驱动(以 MySQL 和 PostgreSQL 为例)
go get -u gorm.io/driver/mysql   # MySQL
go get -u gorm.io/driver/postgres # PostgreSQL
go get -u gorm.io/driver/sqlite   # SQLite
go get -u gorm.io/driver/sqlserver # SQL Server

第一个程序

MySQL 版

package main

import (
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

func main() {
    // 构建 DSN(Data Source Name)
    dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // GORM 会自动维护一个连接池,无需手动关闭单次连接
    // 如果需要关闭整个连接池(一般在程序退出时),通过 sqlDB 操作:
    // sqlDB, _ := db.DB()
    // defer sqlDB.Close()

    // 自动迁移(开发环境)
    db.AutoMigrate(&User{})

    // CRUD 操作
    db.Create(&User{Name: "张三", Age: 18})

    var user User
    db.First(&user, 1) // 按主键查找
    db.First(&user, "name = ?", "张三") // 按条件查找

    db.Model(&user).Update("Age", 20)
    db.Delete(&user, 1)
}

type User struct {
    ID   uint   `gorm:"primaryKey"`
    Name string `gorm:"size:100"`
    Age  int
}

PostgreSQL 版

import (
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

func main() {
    dsn := "host=localhost user=postgres password=pass dbname=mydb port=5432 sslmode=disable TimeZone=Asia/Shanghai"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }
    // ...
}

MySQL DSN 参数速查

参数 说明 推荐值
charset 字符集 utf8mb4(支持 Emoji)
parseTime DATE/DATETIME 转为 time.Time True(必须开启,否则 Scan 报错)
loc 时区 LocalAsia%2FShanghai
timeout 连接超时 10s
readTimeout 读超时 30s
writeTimeout 写超时 30s

示例 DSN:

user:pass@tcp(127.0.0.1:3306)/mydb?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s

🚨 陷阱parseTime=True 必须设置,否则查询 DATETIME 字段时 Scan 会报错 unsupported Scan, storing driver.Value type []uint8 into type *time.Time


PostgreSQL DSN 参数速查

参数 说明 推荐值
host 主机地址 localhost
port 端口 5432
user 用户名
password 密码
dbname 数据库名
sslmode SSL 模式 disable(本地)/require(生产)
TimeZone 会话时区 Asia/Shanghai

示例 DSN:

host=localhost user=postgres password=pass dbname=mydb port=5432 sslmode=disable TimeZone=Asia/Shanghai

gorm.Config 核心配置

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
    // 是否跳过默认事务(默认 false,每个写操作包裹在事务中)
    SkipDefaultTransaction: false,

    // 命名策略(表名、列名规则)
    NamingStrategy: schema.NamingStrategy{
        TablePrefix:   "t_",    // 表名前缀
        SingularTable: true,    // 使用单数表名(默认复数)
        NoLowerCase:   false,   // 禁用小写转换
    },

    // 关闭外键约束(迁移时不创建物理外键)
    DisableForeignKeyConstraintWhenMigrating: true,

    // Logger 配置
    Logger: logger.Default.LogMode(logger.Info),

    // 预备语句缓存(提升性能)
    PrepareStmt: true,

    // 启用 DryRun 模式(只生成 SQL 不执行)
    DryRun: false,
})
配置项 类型 默认值 说明
SkipDefaultTransaction bool false 跳过默认事务,写操作不再自动包裹
NamingStrategy NamingStrategy 表名/列名/外键命名规则
DisableForeignKeyConstraintWhenMigrating bool false 禁用物理外键约束创建
Logger logger.Interface logger.Default SQL 日志输出配置
PrepareStmt bool false 启用预编译语句缓存
DryRun bool false 只生成 SQL 不执行(调试用)
NowFunc func() time.Time 自定义 time.Now()(时区测试用)

💡 最佳实践:开发环境开启 Logger: logger.Default.LogMode(logger.Info) 以查看所有 SQL;生产环境使用 logger.Warn 级别。启用 PrepareStmt 可提升约 10%~20% 的重复查询性能。


获取底层 *sql.DB

GORM 使用 database/sql 作为底层连接池,通过 db.DB() 获取:

sqlDB, err := db.DB()

// 连接池配置
sqlDB.SetMaxIdleConns(10)           // 最大空闲连接数
sqlDB.SetMaxOpenConns(100)          // 最大打开连接数
sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大存活时间
sqlDB.SetConnMaxIdleTime(10 * time.Minute) // 空闲连接最大存活时间(Go 1.15+)

// Ping 检查连接
if err := sqlDB.Ping(); err != nil {
    log.Fatal(err)
}

💡 最佳实践:生产环境务必设置 SetConnMaxLifetime,否则 MySQL 默认 8 小时断开空闲连接,GORM 不会自动重连。


基本项目结构推荐

project/
├── main.go              // 入口:初始化 DB、启动服务
├── config/
│   └── config.go        // 配置管理(DSN、连接池参数)
├── model/
│   ├── user.go          // User 模型定义
│   └── order.go         // Order 模型定义
├── dao/                 // 数据访问层(或 repository/)
│   ├── user_dao.go
│   └── order_dao.go
├── service/             // 业务逻辑层
│   └── user_service.go
├── handler/             // HTTP 处理函数(若使用 Gin 等框架)
│   └── user_handler.go
└── go.mod

💡 大型项目建议将 DB 实例封装在 DAO 层,Service 层只依赖接口,便于单元测试时 Mock。


常见连接错误速查

错误信息 原因 解决
dial tcp: connect: connection refused 数据库未启动或端口错误 检查数据库服务和端口
Error 1045: Access denied 用户名或密码错误 检查 DSN 中的 user/pass
Error 1049: Unknown database 数据库不存在 先创建数据库:CREATE DATABASE mydb
Error 2002: Can't connect to local MySQL server MySQL 未运行或 socket 路径不对 启动 MySQL 或改用 TCP 连接
pq: password authentication failed PostgreSQL 密码错误 检查 pg_hba.conf 和密码
pq: database "xxx" does not exist PostgreSQL 数据库不存在 先创建数据库
SSL is not enabled on the server PostgreSQL sslmode 不匹配 设置 sslmode=disable
invalid connection 连接已断开(超出存活时间) 设置 SetConnMaxLifetime