mongodb go驱动需显式管理context超时、结构体bson标签、游标错误检查及objectid校验。连接须用context.withtimeout并ping验证;插入需bson标签和omitempty;查询须检查cursor.err();更新推荐bson.d;objectid必须isvalidobjectid校验。

MongoDB 的 Go 驱动(mongo-go-driver)不提供“开箱即用”的 ORM,所有文档操作都围绕 interface{} 或结构体 + bson.M/bson.D 展开,直接写错类型或忽略上下文超时是高频崩溃原因。
连接 MongoDB 时必须显式设置 context 和超时
不带 context 的 Connect() 调用在 DNS 解析失败、网络阻塞时会无限等待;生产环境必须控制初始化耗时。
- 用
context.WithTimeout(context.Background(), 10*time.Second)包裹mongo.Connect() - 连接后立即调用
client.Ping()并传入同一 context,验证连通性 - 全局复用
*mongo.Client实例,不要每次操作都新建 client
插入文档时结构体字段必须带 bson 标签
Go 结构体字段默认不会被序列化进 BSON,漏写 bson tag 会导致写入空文档或字段名错误(如大驼峰变小写下划线)。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 基础写法:
type User struct { ID primitive.ObjectID `bson:"_id,omitempty"` Name string `bson:"name"` } -
omitempty对_id很关键:插入时若未赋值,驱动会自动生成;否则可能因重复_id报duplicate key - 避免用
map[string]interface{}插入——类型丢失、无编译检查、嵌套深时易 panic
查询返回值必须检查 err 和 cursor.Err()
Collection.Find() 返回 *mongo.Cursor,它本身不校验查询语法或权限;真正报错常发生在 Next() 或 Close() 阶段。
- 循环前先判断
err := cursor.Err(),不是只看Find()的 err - 每次
cursor.Next()后必须检查cursor.Err() != nil,否则部分文档解析失败会被静默跳过 - 务必调用
cursor.Close(ctx),否则连接泄漏,mongod连接数会持续上涨
更新操作慎用 $set 直接写入 map
用 bson.M{"$set": map[string]interface{}{"status": "done"}} 看似简洁,但字段名拼错、类型错位(如传 int64 当 float64)、嵌套路径写错都不会在编译期暴露。
- 推荐用结构体 +
bson.E构建更新器:bson.D{{"$set", bson.D{{"status", "done"}}}} - 更新前加
Upsert: true参数需谨慎:意外触发插入可能污染数据逻辑 - 批量更新用
UpdateMany()时,Match条件必须有索引支撑,否则全表扫描在大数据量下直接拖垮集群
最容易被忽略的是 primitive.ObjectIDHex() 的错误处理——字符串长度不对或含非法字符时返回空 ObjectID,后续查询永远匹配不到,且不报错。每次从 HTTP 参数或 JSON 解析出 ID,必须用 primitive.IsValidObjectID() 先校验。










