
使用 mgo 驱动时,Go 结构体字段必须以大写字母开头才能被 bson 包导出并正确映射嵌套文档;小写字段(如 en 或 translatedName)因未导出而被忽略,导致嵌套数据为空。
使用 mgo 驱动时,go 结构体字段必须以大写字母开头才能被 bson 包导出并正确映射嵌套文档;小写字段(如 `en` 或 `translatedname`)因未导出而被忽略,导致嵌套数据为空。
在 Go 中,只有首字母大写的字段才是可导出(exported)的,而 mgo(基于 gopkg.in/mgo.v2)依赖反射机制进行 BSON 序列化/反序列化,它无法访问未导出(小写开头)的字段。因此,尽管你的 MongoDB 文档中存在 en.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 → 不可导出 → 被忽略
}
即使 bson tag 存在,mgo 也不会尝试将 BSON 中的 "en" 对象解码到该字段——它直接跳过,最终 result.en 保持零值(即空结构体 {})。
✅ 正确做法是:所有需参与 BSON 编解码的结构体字段必须首字母大写,并配合正确的 bson tag 显式指定底层字段名:
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 + bson:"en"
}
完整工作示例:
func getJobTypeByID(session *mgo.Session, id string) (*JobType, error) {
sessionCopy := session.Copy()
defer sessionCopy.Close()
c := sessionCopy.DB(os.Getenv("DB_DATABASE")).C("jobTypes")
var result JobType
err := c.FindId(id).One(&result)
if err != nil {
return nil, err
}
fmt.Printf("EN translation: %s\n", result.En.TranslatedName) // 输出: Packing and Order Prep
return &result, nil
}
⚠️ 注意事项:
-
bsontag 中的键名(如"en"、"translatedName")必须与 MongoDB 文档中的字段名完全一致(包括大小写); - Go 结构体字段名(如
En、TranslatedName)仅用于 Go 内部访问,其大小写不影响 BSON 映射逻辑,但必须可导出; - 若需兼容 JSON API 输出,可同时保留
jsontag(如json:"en"),与bsontag 独立配置; - 推荐结构体名采用 PascalCase(如
JobType),符合 Go 社区惯例且避免混淆。
总结:mgo 的字段映射本质是「导出字段 + tag 控制」,不是纯名称匹配。牢记 —— 小写 = 不可见 = 不映射。这是初学者最常踩的“静默失败”陷阱之一。











