go中mongo.collection.find必须传带超时的context,filter需用bson.m或map[string]interface{},查完须调用all或next+close释放资源,空结果不报错而需判长度。

Go 用 mongo.Collection.Find 查文档,必须传 context.Context
不传 context 或传 context.TODO() 看似能跑,但一到超时、取消或连接中断就卡死或 panic。MongoDB Go 驱动所有阻塞操作(包括 Find)都强依赖 context 控制生命周期。
- 生产环境一律用带超时的 context,比如
context.WithTimeout(ctx, 5*time.Second) - 不要在 handler 里复用 HTTP request context 直接传给
Find——它可能在查询中途被 cancel,导致context canceled错误 - 如果只是本地调试,可用
context.Background(),但得清楚它没有超时和取消能力
Find 的 filter 参数必须是 map[string]interface{} 或 bson.M
直接传 struct、JSON 字符串或 nil 会静默失败或返回空结果,不是报错——这是新手最常踩的坑。驱动不会自动序列化任意 Go struct,除非你显式用 bson.M 或 bson.D 构建 filter。
- 推荐用
bson.M{"name": "Alice", "age": bson.M{"$gt": 18}},语义清晰且类型安全 - 避免用
map[string]interface{}嵌套太深,容易漏写 key 类型(比如把int64当int传,MongoDB 可能匹配不到) - 字段名要和数据库实际存储一致——区分大小写,且不自动转换驼峰为下划线(除非你配了 struct tag,但 filter 本身不走 tag)
查完必须调用 Cursor.All 或循环 Cursor.Next,否则资源不释放
Find 返回的是 *mongo.Cursor,它持有网络连接和内存缓冲区。不消费完或不关闭,会导致 goroutine 泄漏、连接耗尽、后续查询变慢甚至超时。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 简单场景用
cursor.All(ctx, &results),results是切片指针,驱动自动解码 - 大数据量或流式处理,必须用
for cursor.Next(ctx) { ... }+defer cursor.Close(ctx) - 忘了
defer cursor.Close(ctx)?哪怕用了All,也建议加 defer——All 内部会 close,但显式关更可控
空结果不报错,len(results) 为 0 就是没查到
很多人以为没匹配到会 panic 或返回 error,其实 Find + All 成功时 error 一定为 nil,哪怕集合为空或 filter 完全不匹配。判断“查不到”只能看结果长度或用 cursor.Next 是否返回 false。
- 别写
if err != nil { /* 没查到 */ }——这是错的,err 不为 nil 表示连接失败、权限不足或 BSON 解析错误 - 想查单条且确保存在?用
FindOne更合适;它返回ErrNoDocuments可明确区分“无数据”和“其他错误” - 聚合或复杂查询里,
$lookup结果为空数组也是合法响应,不能靠 error 判断
真正麻烦的是 filter 写对了、context 设好了、cursor 也关了,结果还是空——八成是字段类型不一致(比如存的是 string 的 "123",却用 int 去查),或者 ObjectId 生成方式不对(primitive.ObjectIDHex 解析失败却不检查 error)。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










