Gin 实战 6:接入数据库与 GORM
后台系统的数据最终要落到 MySQL。本章接入 GORM,完成数据库配置、连接池和全局 *gorm.DB 初始化。
1. 安装依赖
bash
go get gorm.io/gorm
go get gorm.io/driver/mysql2. 补充数据库配置
configs/dev.yaml:
yaml
database:
host: 127.0.0.1
port: 3306
username: root
password: root
dbname: youlai_admin
charset: utf8mb4
parseTime: true
loc: Local
maxIdleConns: 10
maxOpenConns: 100
connMaxLifetime: 36003. 生成 DSN
创建 internal/common/database/config.go:
go
package database
import "fmt"
type Config struct {
// 基础连接信息,对应 MySQL 地址、端口和账号密码。
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
DBName string `mapstructure:"dbname"`
// DSN 参数。parseTime=true 可以让 MySQL 时间字段正确映射到 time.Time。
Charset string `mapstructure:"charset"`
ParseTime bool `mapstructure:"parseTime"`
Loc string `mapstructure:"loc"`
// 连接池参数,避免每次请求都新建数据库连接。
MaxIdleConns int `mapstructure:"maxIdleConns"`
MaxOpenConns int `mapstructure:"maxOpenConns"`
ConnMaxLifetime int `mapstructure:"connMaxLifetime"`
}
// DSN 把结构化配置拼成 MySQL Driver 需要的连接字符串。
func (c Config) DSN() string {
return fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=%t&loc=%s",
c.Username, c.Password, c.Host, c.Port, c.DBName,
c.Charset, c.ParseTime, c.Loc,
)
}把第二章的 Config.Database 类型替换为 database.Config。
4. 初始化 GORM
创建 internal/common/database/database.go:
go
package database
import (
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// DB 保存全局数据库连接。
// 简化阶段先全局使用,后面 Repository 会通过它访问数据库。
var DB *gorm.DB
func Init(cfg Config) error {
// 使用配置生成 DSN,并创建 GORM 连接。
db, err := gorm.Open(mysql.Open(cfg.DSN()), &gorm.Config{})
if err != nil {
return err
}
// GORM 底层仍然使用 database/sql,这里取出底层连接池做参数设置。
sqlDB, err := db.DB()
if err != nil {
return err
}
// 最大空闲连接数:控制空闲连接池大小。
sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)
// 最大打开连接数:控制应用最多占用多少数据库连接。
sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
// 单个连接最大复用时间,避免长连接一直不释放。
sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetime) * time.Second)
// 初始化成功后赋值给全局 DB,供 Repository 使用。
DB = db
return nil
}5. main.go 接入数据库
go
// 数据库初始化应放在路由注册之前。
// 如果数据库不可用,服务不应该继续启动。
if err := database.Init(config.Cfg.Database); err != nil {
log.Fatalf("数据库初始化失败: %v", err)
}启动时如果数据库连不上,服务直接失败。这样比接口运行时才报错更早、更清楚。下一章基于 GORM 写用户 CRUD。
