
在使用 mgo 驱动时,若结构体字段未通过 bson 标签显式声明对应数据库字段名,Go 会默认将字段名小写化(如 InitialDiseaseColouring → initialdiseasecolouring),导致无法匹配 MongoDB 中带大小写的字段(如 initialDiseaseColouring),从而读取为空。
在使用 mgo 驱动时,若结构体字段未通过 `bson` 标签显式声明对应数据库字段名,go 会默认将字段名小写化(如 `initialdiseasecolouring` → `initialdiseasecolouring`),导致无法匹配 mongodb 中带大小写的字段(如 `initialdiseasecolouring`),从而读取为空。
MongoDB 是区分字段大小写的,而 Go 的结构体字段在序列化/反序列化为 BSON 时,默认采用 小写蛇形(lowercase snake case) 规则——即把 InitialDiseaseColouring 自动转为 initialdiseasecolouring。但你的文档中实际存储的是 initialDiseaseColouring(驼峰式、首字母小写、内部大写),因此 mgo 找不到匹配字段,该字段值保持零值(空字符串)。
✅ 正确做法是:为每个需精确映射的字段添加 bson struct tag,显式指定其对应的 BSON 字段名:
type City struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string `bson:"name"`
InitialDiseaseColouring string `bson:"initialDiseaseColouring"`
}
? 注意:bson:"name" 虽然可省略(因 Name 默认映射为 "name"),但显式声明更清晰、更安全;而 InitialDiseaseColouring 必须显式标注,否则默认变为 initialdiseasecolouring,与数据库不一致。
完整查询示例:
result := City{}
err := collection.Find(bson.M{"name": "Reykjavik"}).One(&result)
if err != nil {
log.Fatal("Query failed:", err)
}
fmt.Printf("%+v\n", result) // 输出: {ID:ObjectIdHex("...") Name:"Reykjavik" InitialDiseaseColouring:"blue"}
⚠️ 补充注意事项:
- bson.ObjectId 已在较新版本 mgo 中弃用,推荐升级至 primitive.ObjectID 并使用官方 go.mongodb.org/mongo-driver/mongo 驱动;
- 若字段名含下划线(如 initial_disease_colouring),也需用 bson:"initial_disease_colouring" 显式声明;
- 使用 omitempty 仅影响序列化(写入)时是否忽略零值字段,不影响反序列化(读取)行为。
总之,结构体字段与 BSON 字段的映射必须显式、精确——依赖默认规则极易因大小写或命名风格差异导致静默失败。始终为非标准命名的字段添加 bson tag,是保障数据正确绑定的关键实践。











