fiber本身不管理数据库连接,所有配置均由所选数据库驱动和orm决定;必须显式配置gorm.open()连接池参数,否则高并发下必现连接耗尽或超时。

Fiber 本身不安装数据库驱动,也不管理连接——你装什么库、怎么连、连不连得上,全由你选的数据库驱动和 ORM 决定;装错版本、漏设连接池、硬编码 DSN,上线后必挂。
go get 命令必须匹配 Go 版本和 Fiber 大版本
Go 1.21+ 用 go get github.com/gofiber/fiber/v2;Go 1.24+ 才能用 v3。v2 是当前生产唯一稳定选择,v3 的文档和生态(比如 gorm.io/driver/postgres)尚未完全对齐,混用会编译失败或运行时 panic。
别信“go get -u github.com/gofiber/fiber”这种写法——它可能拉到 v1(已归档)、v2 或 v3 中任意一个,版本漂移风险极高。
- 检查 Go 版本:
go version,低于 1.21 就先升级 - 初始化模块:
go mod init example.com/myapp,再执行go get github.com/gofiber/fiber/v2 - 如果后续要加 GORM + PostgreSQL:
go get gorm.io/gorm gorm.io/driver/postgres,注意不是github.com/jinzhu/gorm(老版已弃用)
数据库依赖不能只装 ORM,还要装对应驱动和连接池配置
只写 go get gorm.io/gorm 是没用的——GORM 是抽象层,真正建连接靠驱动。PostgreSQL 要 gorm.io/driver/postgres,MySQL 要 gorm.io/driver/mysql,SQLite 要 gorm.io/driver/sqlite。漏装驱动,gorm.Open() 直接 panic:"unsupported driver: postgres"。
更关键的是:驱动装上了,gorm.Open() 调通了,不代表能扛住并发。默认 *sql.DB 的 MaxOpenConns=0(无上限)、MaxIdleConns=2,压测时很快出现 dial tcp: i/o timeout 或连接耗尽。
- 初始化后立刻调:
db.DB().SetMaxIdleConns(10)、db.DB().SetMaxOpenConns(50)、db.DB().SetConnMaxLifetime(1 * time.Hour) -
SetConnMaxLifetime单位是time.Duration,写成"1h"会编译失败 - PostgreSQL DSN 必须含
sslmode=disable,否则默认走 SSL 握手,本地开发连不上还报错静默
DSN 字符串不能硬编码,环境变量组装是底线
把 "host=localhost user=postgres password=postgres dbname=test" 写死在代码里,等于把密码明文提交进 Git。CI/CD 流水线一跑,所有密钥全泄露。
DSN 格式因数据库而异,拼错一个字符就失败,且错误信息极不友好(比如 MySQL 报 invalid connection,PostgreSQL 报 failed to connect to `host=localhost user=postgres database=test`: dial error),根本看不出是哪字段错了。
- 正确做法:从环境变量读取各段,再拼接:
os.Getenv("DB_HOST") + " user=" + os.Getenv("DB_USER") + " password=" + os.Getenv("DB_PASSWORD") + " dbname=" + os.Getenv("DB_NAME") + " sslmode=disable" - MySQL DSN 必须带
parseTime=True,否则time.Time字段扫描失败;PostgreSQL 不需要 - SQLite DSN 后要加
?_foreign_keys=1,否则外键约束不生效
启动时不做健康检查,等于带着病服务上线
很多人写完 gorm.Open() 就直接 app.Listen(),但网络不通、密码错、数据库没启、RDS Proxy 拒绝连接……这些情况 gorm.Open() 都不会立即报错,而是延迟到第一次 db.First() 才 panic,导致服务已监听端口却无法响应请求。
Redis 同理:用 redis.NewClient() 初始化后,不调 client.Ping(ctx).Err(),你就永远不知道缓存是否真连上了。
- 务必在
main()里加:if err := db.Exec("SELECT 1").Error; err != nil { log.Fatal("DB health check failed:", err) } - Redis 检查写法:
if err := client.Ping(context.Background()).Err(); err != nil { log.Fatal("Redis health check failed:", err) } - 健康检查的 context 别用
context.TODO(),至少用context.WithTimeout(context.Background(), 5*time.Second)
最容易被忽略的点:连接池参数不是“配一次就完事”,而是必须按压测结果调。线上 QPS 从 100 涨到 2000,MaxOpenConns 不跟着扩,照样超时;ConnMaxLifetime 设太短,频繁重连反而拖垮性能。没有银弹,只有实测。











