fiber本身不提供数据库连接能力,所有连接必须由开发者用driver(如mongo-go-driver)自行初始化并管理;生产环境需用带超时的context连接、显式配置连接池、从环境变量读uri、严格使用bson tag、游标必须close且绑定请求ctx。

直接说结论:Fiber 本身不提供数据库连接能力,所有连接逻辑必须由你用 driver(如 mongo-go-driver、gorm、pgx)自行初始化并管理;关键不是选什么框架,而是连接怎么建、上下文怎么传、资源怎么收。
mongo-go-driver 连接必须带超时 context,不能用 context.TODO()
常见错误是写成 client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri)),这会导致连接卡死或 panic。生产环境必须显式设超时,并验证连通性:
- 用
context.WithTimeout(ctx, 10*time.Second)包裹mongo.Connect和后续的client.Ping() -
client.Ping()必须传新 context(不能复用 Connect 时的),否则超时逻辑失效 - 连接池参数要显式配置:
options.Client().SetMaxPoolSize(20).SetMinPoolSize(5).SetConnectTimeout(5 * time.Second) - URI 务必从环境变量读取,如
os.Getenv("MONGODB_URI"),避免硬编码 localhost 或密码泄露
结构体字段必须用 bson tag,不是 json tag
Go 结构体映射 BSON 文档完全依赖 bson tag,漏写、拼错或类型不匹配,FindOne 就返回空值但不报错——这是最隐蔽的 bug 来源:
- ID 字段必须写成
ID primitive.ObjectID `bson:"_id,omitempty"`,下划线不能少,“omitempty” 影响插入时是否生成新_id - 时间字段类型必须是
time.Time,tag 写成bson:"created_at",不能是字符串或int64 - 嵌套结构体每一层都要加
bsontag,否则子字段不会被序列化/反序列化 - 如果用
bson.M手动构造查询条件,key 是字符串,value 类型必须和数据库字段一致(比如"age": 25不能写成"age": "25")
Find() 游标必须 Close(),且 defer 要绑定当前请求 context
Find() 返回的 *mongo.Cursor 底层持有网络连接和缓冲区,不 Close 就会泄漏 goroutine 和内存,尤其在高并发下很快 OOM:
- 必须写
defer cursor.Close(ctx),这里的ctx应该是 handler 入参的请求生命周期context,不是全局context - 遍历游标必须先
cursor.Next(),再cursor.Decode();跳过Next直接Decode会 panic - 批量结果可用
cursor.All()转切片,但要注意内存占用;流式处理更安全,适合大结果集
用 GORM 时,Connect() 函数要负责迁移和复用
Fiber 不管你用不用 ORM,GORM 的初始化仍需你自己把控:
- 推荐封装一个
initDB()或Connect()函数,统一处理连接、日志开关、连接池配置和自动迁移 - PostgreSQL 示例 DSN:
"host=localhost user=postgres password=postgres dbname=fiber_demo port=5432 sslmode=disable" - 别在每个 handler 里重复调用
gorm.Open;Client / DB 实例应全局复用,否则连接池失效、性能暴跌 - 如果用
gorm.Model(&User{}).Where(...).First(),确保表已存在或已执行AutoMigrate
真正容易被忽略的不是“怎么连”,而是“谁来关”——连接池没配、游标没关、context 没传对、bson tag 拼错,这些都不会立刻报错,但会在压测或上线后集中爆发。Fiber 的轻量,意味着它把控制权全交给你,也把责任全交给你。











