用 database/sql 配合 go-sql-driver/mysql 是唯一可行方式;fiber 无数据库层,需手动初始化 *sql.db、调用 db.ping() 校验连接、配置连接池参数,并安全传入处理器,查询时须检查错误并 defer rows.close()。

用 database/sql 配合 mysql 驱动是唯一可行方式
Fiber 本身不提供数据库连接层,它只是 HTTP 路由框架。所有数据库操作必须通过 Go 标准库 database/sql + 第三方驱动(如 go-sql-driver/mysql)完成。别被“Fiber ORM”这类模糊搜索误导——目前没有官方或主流维护的 Fiber 原生 ORM,强行找封装反而增加抽象泄漏风险。
实操建议:
- 直接
go get github.com/go-sql-driver/mysql,这是最稳定、文档最全的 MySQL 驱动 - 不要用
github.com/jmoiron/sqlx或gorm.io/gorm等 ORM “自动集成 Fiber”,它们和 Fiber 无耦合关系,所谓“集成”只是你把 DB 实例挂到fiber.Ctx.Locals或全局变量里 - 连接字符串格式必须为:
user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true&loc=Local;注意&是 HTML 实体,在 Go 字符串里要写成&
sql.Open 不等于连接成功,必须显式调用 db.Ping()
常见错误:代码跑起来没报错,但首次查询时才爆出 dial tcp 127.0.0.1:3306: connect: connection refused。这是因为 sql.Open 只校验 DSN 格式,不真正建连。
正确做法:
- 在应用启动时(如
main()函数里)立即执行db.Ping(),失败就log.Fatal退出 - 设置连接池参数:用
db.SetMaxOpenConns(20)和db.SetMaxIdleConns(10),避免默认无限开连导致 MySQL 报Too many connections - 如果用 Docker 启动 MySQL,确保 Fiber 服务容器能解析并访问
mysql:3306(不是localhost:3306)
把 *sql.DB 安全传入 Fiber 路由处理器
Fiber 的 fiber.Handler 函数签名是 func(c *fiber.Ctx) error,没有内置依赖注入。DB 实例不能靠闭包捕获(易引发并发问题),也不能反复 sql.Open(浪费资源)。
推荐方案:
- 定义全局变量
var DB *sql.DB,在main()初始化后直接使用——对中小型项目足够清晰 - 若需测试或解耦,用
c.Locals挂载:app.Use(func(c *fiber.Ctx) error { c.Locals("db", DB); return c.Next() }),然后在路由里取c.Locals("db").(*sql.DB) - 避免用
context.WithValue手动塞 DB,Fiber 的Ctx.Context()是请求上下文,不是依赖传递通道
查询时别漏掉 rows.Close() 和错误检查
典型翻车现场:rows, _ := db.Query("SELECT id FROM users"),后面直接 for rows.Next(),但没 defer rows.Close()。这会导致连接长期占用,很快耗尽 max_connections。
安全写法要点:
- 总是检查
err:无论是db.Query、rows.Scan还是rows.Close()都可能返回错误 - 用
defer rows.Close()放在rows, err := ...之后立刻执行,哪怕err != nil也要关(rows可能非 nil) - 批量插入优先用
db.Exec("INSERT INTO ... VALUES (?, ?), (?, ?)", ...),别循环单条Exec,性能差一个数量级
最常被忽略的是连接池超时和 DNS 缓存——MySQL 重启后,已建立的空闲连接不会自动失效,直到下次复用时才报错。生产环境务必配 db.SetConnMaxLifetime(60 * time.Second) 主动轮换。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











