
mgo 要求 go 结构体字段名首字母大写(导出字段)才能被 bson 解析器识别并反序列化嵌套子文档,小写字段会被忽略,导致嵌套数据为空。
mgo 要求 go 结构体字段名首字母大写(导出字段)才能被 bson 解析器识别并反序列化嵌套子文档,小写字段会被忽略,导致嵌套数据为空。
在使用 mgo 操作 MongoDB 时,结构体字段的可见性直接影响 BSON 反序列化的结果。Go 语言规定:只有首字母大写的字段才是导出字段(exported),才能被外部包(如 mgo)反射访问;而小写字母开头的字段(如 en、translatedName)属于非导出字段,在 BSON 解析过程中会被完全忽略——这正是你看到 result.en 输出为 {} 的根本原因。
✅ 正确做法是将嵌套结构体字段全部改为导出字段,并保持 BSON 标签与数据库字段一致:
type JobTypeWording struct {
TranslatedName string `json:"translatedName" bson:"translatedName"`
}
type JobType struct {
ID string `json:"_id" bson:"_id"`
Name string `json:"name" bson:"name"`
Category string `json:"category" bson:"category"`
En JobTypeWording `json:"en" bson:"en"` // 注意:字段名 En(大写E)+ bson:"en"
}
调用代码无需修改,仍可正常使用:
result := JobType{}
sessionCopy := session.Copy()
defer sessionCopy.Close()
c := sessionCopy.DB(os.Getenv("DB_DATABASE")).C("jobTypes")
err := c.Find(bson.M{"_id": id}).One(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.En.TranslatedName) // 输出: "Packing and Order Prep"
⚠️ 注意事项:
-
bson标签指定数据库中实际的字段名(如"en"、"translatedName"),必须与 MongoDB 文档严格匹配; - Go 字段名(如
En、TranslatedName)必须首字母大写,否则 mgo 无法读写该字段; - JSON 标签(
json:"...")仅影响 JSON 序列化,对 mgo 无影响,但建议保持一致性; - 若需兼容旧版代码或避免结构体暴露,可配合
json:"-"隐藏某些字段,但bson标签仍需保留。
? 小结:mgo 不是“按标签名反射”,而是“按导出字段名 + 标签”协同工作。始终确保嵌套结构体及其所有层级字段均为导出字段,这是正确解析嵌套 BSON 文档的前提。











