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

直接说结论:Fiber 本身不管理数据库连接,所有配置都由你选用的数据库驱动和 ORM 决定;强行套用“Fiber 数据库配置”这种说法,只会让你漏掉关键参数、压测时连不上、或上线后内存泄漏。
gorm.Open() 必须显式配置连接池,否则高并发必挂
很多人写 gorm.Open(mysql.Open(dsn), &gorm.Config{}) 就完事,但底层 *sql.DB 默认 MaxIdleConns=2、MaxOpenConns=0(即无上限),实际运行中会快速耗尽连接或卡在 dial tcp: i/o timeout。
- 初始化后必须立刻调
db.DB().SetMaxIdleConns(10)和db.DB().SetMaxOpenConns(50),数值按压测结果调,别照搬 -
SetConnMaxLifetime(1 * time.Hour)必设——MySQL 默认wait_timeout=8h,但网络中间件(如 ProxySQL、RDS Proxy)可能更早断连,不设会导致僵死连接堆积 -
SetConnMaxLifetime单位是time.Duration,不是字符串,写成"1h"会编译失败
PostgreSQL / MySQL / SQLite 的 DSN 差异不能硬套
同一个 gorm.Open() 调用,换数据库类型就得换 DSN 格式,字段名、分隔符、必填项全不同,拼错一个就报 invalid connection 或静默失败。
- PostgreSQL:
host=localhost user=postgres password=postgres dbname=test port=5432 sslmode=disable,sslmode不加会默认尝试 SSL,连不上 - MySQL:
user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local,parseTime=True才能正确扫描time.Time字段 - SQLite:
test.db?_foreign_keys=1,_foreign_keys=1要显式开,否则外键约束不生效
Redis 连接别找 “Fiber-Redis” 包,go-redis/v9 才是唯一正解
Fiber 没有、也不需要 Redis 官方集成包。所谓 “Fiber-Redis 中间件” 多是过时封装,把 *redis.Client 塞进 ctx.Locals 还会加重 GC 压力。
- 用
redis.NewClient(&redis.Options{Addr: "localhost:6379", Password: "", DB: 0, PoolSize: 20})初始化,Password字段不能为空字符串,否则认证失败 - 启动时必须做健康检查:
if err := client.Ping(ctx).Err(); err != nil { log.Fatal(err) },别让服务带病运行 - Handler 里读写缓存,直接闭包捕获 client 实例即可,例如:
func(c *fiber.Ctx) error { val, err := client.Get(c.Context(), "key").Result() } -
client.Get().Result()返回string,如果之前存的是 JSON,得自己json.Unmarshal([]byte(val), &v),不能直接当 struct 用
MongoDB 的 bson tag 错一个字母就查不到数据
Go 的 mgo 或 mongo-go-driver 完全不认 json: tag,只看 bson:。字段名大小写、下划线、嵌套结构全要严格对齐数据库实际存储格式,否则 Find() 返回空、Insert() 存进去却是空对象。
-
_id字段必须写bson:"_id,omitempty",少下划线或写成id都无效 - 时间字段必须是
time.Time类型 +bson:"created_at",写成string或 tag 用createdat就无法映射 - 嵌套 struct 如
User struct{ Name string `bson:"name"` },内层也要单独打 tag,不会继承外层前缀 -
collection.Find()返回的*mongo.Cursor必须显式defer cursor.Close(ctx),漏掉就会 goroutine 和内存持续泄漏,压测几分钟就 OOM
最常被忽略的其实是连接生命周期管理:数据库 client 必须在 main() 启动阶段初始化并复用,绝不能在 handler 里 new,也别 defer Close。真正的难点不在语法,而在每个驱动对「连接」的语义定义完全不同——MySQL 认为断连可重试,MongoDB 要求游标及时释放,Redis 连接池要防超时穿透。配错一个参数,表现出来的可能只是接口偶尔超时,而不是立刻报错。











