必须显式设置超时context和连接池参数:用context.withtimeout(ctx, 10time.second)调用mongo.connect(),配合options.client().setconnecttimeout(5time.second)、setmaxpoolsize(20)、setminpoolsize(5),uri须从环境变量读取,bson tag错写会导致findone静默返回空值。

mongo-go-driver 连接配置必须带超时 context
直接用 context.TODO() 调用 mongo.Connect() 是线上事故高发点——它会让 goroutine 卡死在 DNS 解析或 TCP 握手阶段,且无法被外部取消。生产环境必须显式设置连接超时和池参数。
-
context.WithTimeout(ctx, 10*time.Second)传给mongo.Connect(),避免阻塞超过阈值 - 通过
options.Client().SetConnectTimeout(5*time.Second)控制建连本身耗时 - 用
SetMaxPoolSize(20)和SetMinPoolSize(5)匹配预估 QPS;过小导致排队,过大浪费内存 - URI 必须从环境变量读取(如
os.Getenv("MONGODB_URI")),禁止硬编码localhost:27017
bson tag 写错会导致 FindOne 返回 nil 而不报错
Go 结构体映射 BSON 文档完全依赖 bson tag,不是 json。漏写、拼错或类型不匹配,FindOne() 会静默返回空值,极易误判为“查无数据”。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- ID 字段必须写成
ID primitive.ObjectID `bson:"_id,omitempty"`,下划线不能少,omitempty影响插入时是否生成新_id - 时间字段类型必须是
time.Time,tag 写成bson:"created_at",不能是字符串或int64 - 嵌套结构体每一层都要加
bsontag,否则子字段不会被序列化/反序列化 - 若用
bson.M手动构造查询,value 类型需与库中字段一致(如"age": 25不能写成"age": "25")
游标(Cursor)不 Close 会引发 goroutine 泄漏
Find() 返回的 *mongo.Cursor 持有网络连接和缓冲区,不显式关闭会在请求结束后持续占用资源,长期运行必然 OOM。
- 必须在函数入口处
defer cursor.Close(ctx),且ctx应为当前 HTTP 请求生命周期的 context - 遍历前必须先调用
cursor.Next(ctx),再调用cursor.Decode(&v);跳过Next()直接Decode()会 panic - 批量结果可用
cursor.All(ctx, &results)转切片,但注意内存峰值;高并发建议流式Next()+ 处理 - 解码失败时
cursor.Err()才返回非 nil 错误,不能只检查Next()返回值
UpdateOne 的 filter 和 update 参数顺序不可颠倒
collection.UpdateOne() 第一个参数是 filter(查询条件),第二个才是 update(更新操作符),顺序反了会导致文档被错误覆盖或静默失败。
- 正确写法:
collection.UpdateOne(ctx, bson.M{"_id": id}, bson.M{"$set": bson.M{"name": "new"}}) - 常见错误:把
bson.M{"$set": ...}当作第一个参数,结果 MongoDB 尝试用更新语句当 filter 匹配,查不到任何文档 - 使用
$set、$inc等操作符时,外层必须是bson.M,不能直接传 struct 或 map[string]interface{} - 更新后检查
result.MatchedCount和result.ModifiedCount,区分“找到但未修改”和“根本没找到”
mongo-go-driver 的使用细节:context 生命周期、bson tag 精确性、游标释放时机、UpdateOne 参数顺序。这些点一旦疏忽,轻则查询失真,重则服务缓慢甚至崩溃。










