最稳妥的mongodb连接方式是mongo.connect+context.withtimeout+options.client().applyuri;必须显式设超时避免goroutine泄漏,uri需正确指定authsource、tls及特殊字符编码,client应全局复用并正确关闭。

用 go.mongodb.org/mongo-driver/mongo 是唯一靠谱的选择,mgo 和 gopkg.in/mgo.v2 已归档、不支持 MongoDB 4.4+ 的 SCRAM-SHA-256 认证,连接会静默失败或 panic。
mongo.Connect 必须配超时 context,不能用 context.Background()
默认 mongo.Connect 有 30 秒隐式超时,但协程卡住无法取消,生产环境极易引发 goroutine 泄漏。必须显式构造带 deadline 的 context:
-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)—— 超时设为 10 秒较稳妥,短于 MongoDB 默认 connectTimeout(30s)但留出 ping 验证余量 - 务必
defer cancel(),否则 context 泄漏 - 不要传
nil给client.Ping,应传readpref.Primary():client.Ping(ctx, readpref.Primary()),否则副本集环境下可能误连 secondary 并返回 stale 数据
URI 中 authSource、TLS、特殊字符一个都不能漏
本地开发用 mongodb://localhost:27017 没问题,上生产必须含认证参数,否则报 not authorized on myapp to execute command:
- 用户在
admin库创建,操作myapp库时,URI 必须写成:mongodb://user:pass@host:27017/myapp?authSource=admin - TLS 启用时,测试环境加
?tls=true&tlsInsecure=true;生产环境必须指定 CA:?tls=true&tlsCAFile=/etc/ssl/mongo-ca.pem,否则连接卡住或直接connection refused - 密码含
/、@、:等字符时,必须用url.PathEscape()编码,否则 URI 解析失败,错误信息是模糊的invalid URI或静默连接失败
结构体 bson tag 错一个字母,Decode 就全为零值
MongoDB 字段名大小写敏感,且驱动完全不校验 schema,字段映射失败不会报错,只会把 struct 字段设为零值:
- 必须每个字段都加
bsontag,例如Name string `bson:"name"`,漏写或拼错(如"nmae")会导致 decode 后Name为"" -
_id字段类型必须是primitive.ObjectID,不是string,否则 decode 失败且静默为零值 - 嵌套结构体要逐层加 tag,内层字段不会继承外层前缀;时间字段建议统一存 UTC,filter 里用
time.Now().UTC()对齐 -
bson:",omitempty"对 bool/int 类型慎用——false、0也会被跳过,不是仅跳过 nil
Find 返回的 cursor 必须 Close,否则内存泄漏
collection.Find() 返回 *mongo.Cursor,它持有连接和缓冲区,不 Close 会导致 goroutine 和内存持续增长:
- 绝不能只写
cursor.Next(ctx)就结束,必须配defer cursor.Close(ctx) - 更安全写法是用
for cursor.Next(ctx) { ... }+if err := cursor.Err(); err != nil { ... }+cursor.Close(ctx) - 如果只查一条,优先用
FindOne()+Decode(),避免游标开销 -
*mongo.Client是全局复用对象,不要每次请求 new 一个,但Disconnect()必须在程序退出前调用,否则连接不释放
真正容易被忽略的是:BSON 序列化行为和 Go 值语义的耦合——比如 golang-set 的 MarshalBSONValue 返回数组,但若集合为空,序列化结果是空数组 [],而非 null,查询时 $in: [] 会匹配所有文档,这种逻辑陷阱不会报错,只能靠测试覆盖发现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











