用 GORM 连 MySQL 需安装 gorm.io/gorm 和 gorm.io/driver/mysql,配置含 parseTime=True 和 loc=Local 的 DSN,通过 initDB 初始化并发安全的 *gorm.DB 实例,在 Fiber handler 中直接使用并显式处理错误与事务。

用 GORM 连 MySQL,不是直接连
Fiber 本身不内置 ORM 或数据库驱动,连接 MySQL 必须借助第三方库,GORM 是最常用、最稳妥的选择。别试图用 database/sql 原生写——虽然可行,但手动管理连接池、预处理、事务、结构体映射太容易出错,尤其在 Fiber 的异步/并发场景下。
你真正要配的是:GORM + mysql 驱动(即 github.com/go-sql-driver/mysql),而不是 “Fiber 怎么连 MySQL”。
go get 安装依赖时注意驱动名
运行以下命令安装核心依赖:
go get gorm.io/gorm go get gorm.io/driver/mysql
⚠️ 容易踩的坑:
- 别装
github.com/go-sql-driver/mysql单独包——GORM v2的mysql驱动已封装好,直接用gorm.io/driver/mysql - 如果报
cannot find package "golang.org/x/sys/unix",说明 Go proxy 没配好,临时加:export GOPROXY=https://goproxy.cn,direct - Windows 下若提示
gcc: not found,是缺少 C 编译环境;GORM MySQL 驱动纯 Go 实现,不需要 gcc,换用go-sql-driver/mysql(但推荐坚持用gorm.io/driver/mysql,它更现代)
初始化 GORM 并注入 Fiber 应用上下文
不要把 *gorm.DB 声明为全局变量,而是封装成函数返回,并通过 Fiber 的 c.Locals 或依赖注入传入 handler。简单起见,先放全局(仅限开发验证):
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func initDB() {
dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自动迁移(仅开发期用)
DB.AutoMigrate(&User{})
}
关键点:
-
dsn中必须含parseTime=True,否则time.Time字段会解析失败 -
loc=Local避免时区错乱(MySQL 默认用系统时区,Go 默认 UTC) -
AutoMigrate不会删除字段或改类型,只增不减;上线前务必用 SQL 脚本管理 schema
在 Fiber handler 里安全使用 DB 实例
Fiber 的 handler 是并发执行的,*gorm.DB 本身是并发安全的,但要注意:
- 别在 handler 里反复调用
gorm.Open—— 每次都新建连接池,很快耗尽 MySQL 连接数 - 事务必须显式开启并结束:
tx := DB.Begin(); defer tx.Commit(),别漏Rollback - 查询后记得检查错误:
err := DB.First(&u).Error,GORM不抛 panic(除非配置了Config.NowFunc异常)
一个典型登录校验示例:
app.Post("/login", func(c *fiber.Ctx) error {
type LoginReq struct {
Username string `json:"username"`
Password string `json:"password"`
}
var req LoginReq
if err := c.BodyParser(&req); err != nil {
return c.Status(400).JSON(fiber.Map{"error": "invalid json"})
}
var user User
if err := DB.Where("username = ?", req.Username).First(&user).Error; err != nil {
return c.Status(401).JSON(fiber.Map{"error": "user not found"})
}
if !comparePassword(user.Password, req.Password) {
return c.Status(401).JSON(fiber.Map{"error": "wrong password"})
}
return c.JSON(fiber.Map{"id": user.ID, "username": user.Username})
})
字符集、时区、连接复用、错误判断——这些细节没处理好,上线后第一个高并发请求就可能让服务卡死或返回乱码。别跳过 DSN 参数校验,也别信“本地跑通就行”。


















