835 字
4 分钟
数据源配置

GORM 数据源配置#

连接流程#

GORM 负责 ORM、方言和 SQL 构建;具体驱动负责连接数据库;底层连接池由 Go 标准库 database/sql 管理:

业务代码 -> *gorm.DB -> GORM Dialector/Driver -> *sql.DB -> 数据库

通用初始化流程:

db, err := gorm.Open(dialector, &gorm.Config{})
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
}
sqlDB, err := db.DB()
if err != nil {
return nil, fmt.Errorf("get sql.DB: %w", err)
}
if err := sqlDB.PingContext(ctx); err != nil {
return nil, fmt.Errorf("ping database: %w", err)
}

gorm.Open 成功表示驱动和初始化流程成功,不应替代启动阶段的 PingContext 检查。

驱动安装#

数据库驱动包连接示例
MySQL / MariaDB / TiDBgorm.io/driver/mysqlmysql.Open(dsn)
PostgreSQLgorm.io/driver/postgrespostgres.Open(dsn)
SQLitegorm.io/driver/sqlitesqlite.Open("gorm.db")
SQL Servergorm.io/driver/sqlserversqlserver.Open(dsn)
Oracle使用 GORM Oracle 驱动依赖 Instant Client 和驱动文档

安装示例:

Terminal window
go get gorm.io/gorm
go get gorm.io/driver/mysql

MySQL#

import "gorm.io/driver/mysql"
dsn := "user:password@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

DSN 常用参数:

参数含义
user:password用户名和密码
tcp(127.0.0.1:3306)网络协议、地址和端口
/demo数据库名称
charset=utf8mb4使用完整 UTF-8 字符集
parseTime=True将日期时间解析为 time.Time
loc=Local时间位置

需要驱动高级选项时使用 mysql.New:

db, err := gorm.Open(mysql.New(mysql.Config{
DSN: dsn,
DefaultStringSize: 256,
DisableDatetimePrecision: true,
DontSupportRenameIndex: true,
DontSupportRenameColumn: true,
SkipInitializeWithVersion: false,
}), &gorm.Config{})

PostgreSQL#

import "gorm.io/driver/postgres"
dsn := "host=127.0.0.1 user=postgres password=password dbname=demo port=5432 sslmode=disable TimeZone=Asia/Shanghai"
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})

如果需要关闭 pgx 的隐式 prepared statement,可使用:

db, err := gorm.Open(postgres.New(postgres.Config{
DSN: dsn,
PreferSimpleProtocol: true,
}), &gorm.Config{})

SQLite#

import "gorm.io/driver/sqlite"
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})

内存数据库适合测试:

db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})

SQLite 驱动可能涉及 CGO;若项目要求纯 Go 实现,应按所选替代驱动的文档配置,而不是直接假设所有 SQLite 驱动行为相同。

SQL Server#

import "gorm.io/driver/sqlserver"
dsn := "sqlserver://user:password@127.0.0.1:1433?database=demo"
db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})

连接字符串包含特殊字符时,需要按驱动规则进行 URL 编码,尤其是密码中的 @、:、/ 和 ?。

从环境变量读取配置#

不要把真实密码提交到笔记或源码:

type DatabaseConfig struct {
DSN string
MaxIdleConns int
MaxOpenConns int
ConnMaxLifetime time.Duration
}
func OpenMySQL(cfg DatabaseConfig) (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open(cfg.DSN), &gorm.Config{})
if err != nil {
return nil, err
}
sqlDB, err := db.DB()
if err != nil {
return nil, err
}
sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)
sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
sqlDB.SetConnMaxLifetime(cfg.ConnMaxLifetime)
return db, nil
}
Terminal window
DB_DSN='user:password@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local'

生命周期与连接池#

sqlDB, err := db.DB()
if err != nil {
return err
}
sqlDB.SetMaxIdleConns(10) // 空闲连接上限
sqlDB.SetMaxOpenConns(100) // 打开连接上限
sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大复用时长
sqlDB.SetConnMaxIdleTime(10 * time.Minute)
defer sqlDB.Close() // 应用退出时关闭;不要每次请求都 Close

连接池参数没有通用最佳值,应结合数据库 max_connections、应用实例数量、请求并发和慢查询情况压测。MaxOpenConns 是单个应用实例的上限,不是整个集群的上限。

复用已有 *sql.DB#

已经由其他组件创建连接时,可以把它交给 GORM:

sqlDB, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
db, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB}), &gorm.Config{})

此时连接池仍由这个 sqlDB 管理,避免同一数据库无意中创建两套连接池。

常见问题#

  • parseTime=True 缺失:MySQL 的时间字段可能无法直接映射到 time.Time。
  • 字符集使用 utf8:MySQL 的 utf8 不是完整四字节 UTF-8,优先使用 utf8mb4。
  • 只调用 gorm.Open 不 Ping:启动时无法及时发现网络、认证或数据库不可用。
  • 每次请求创建连接:会造成连接池失控,应在应用启动时创建一次 *gorm.DB。
  • 把 DSN 拼接用户输入:可能产生连接配置注入或解析错误,DSN 应来自可信配置。

官方资料#

数据源配置
https://shirone.mysqil.com/posts/gorm/数据源配置/
作者
HikariTish
发布于
2026-07-30
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取