
在 go 中使用 mgo(或官方驱动)操作 mongodb 时,若结构体字段为小写(未导出),bson 解析器无法访问并赋值,导致反序列化后所有字段为空;必须将字段首字母大写以确保其可导出。
在 go 中使用 mgo(或官方驱动)操作 mongodb 时,若结构体字段为小写(未导出),bson 解析器无法访问并赋值,导致反序列化后所有字段为空;必须将字段首字母大写以确保其可导出。
Go 的反射机制(包括 BSON 序列化库如 mgo 或 go.mongodb.org/mongo-driver/bson)只能访问导出(public)字段——即首字母大写的字段。而你在 StationConfig 中定义的 id 和 name 均为小写,属于未导出字段,因此即使 MongoDB 返回了 _id 和 nm 字段,BSON 解析器也无法写入对应结构体成员,最终输出全为空值。
✅ 正确做法是:将结构体字段改为导出形式,并通过 bson 标签精确映射 MongoDB 字段名:
type StationConfig struct {
ID string `bson:"_id,omitempty"` // 映射 MongoDB 的 "_id" 字段
Name string `bson:"nm"` // 映射 MongoDB 的 "nm" 字段
}
⚠️ 注意事项:
- ID 字段类型建议使用 primitive.ObjectID(官方驱动)或 bson.ObjectId(旧版 mgo),而非 string,以支持 ObjectId 的完整语义(如校验、时间戳解析等)。若坚持用 string,需确保 _id 在 BSON 中能安全转为字符串(通常可行,但会丢失 ObjectId 的结构化能力)。
- omitempty 表示该字段为空时不参与序列化(适用于插入/更新),对读取无影响,可保留。
- 若使用较新的官方 MongoDB Go 驱动(go.mongodb.org/mongo-driver/mongo),请导入 go.mongodb.org/mongo-driver/bson/primitive 并声明:
ID primitive.ObjectID `bson:"_id"`
? 完整修正后的示例(兼容 mgo.v2):
package main
import (
"log"
"gopkg.in/mgo.v2"
)
type StationConfig struct {
ID string `bson:"_id,omitempty"`
Name string `bson:"nm"`
}
func main() {
session, err := mgo.Dial("192.168.1.41")
if err != nil {
panic(err)
}
defer session.Close()
c := session.DB("metos").C("stations")
var stationConfigs []StationConfig
err = c.Find(nil).Limit(100).All(&stationConfigs)
if err != nil {
log.Fatal(err)
}
log.Printf("Found %d stations:\n", len(stationConfigs))
for i, s := range stationConfigs[:min(5, len(stationConfigs))] {
log.Printf(" [%d] ID=%s, Name=%s", i+1, s.ID, s.Name)
}
}
func min(a, b int) int {
if a <p>? 总结:Go 中所有需要被外部包(如 BSON 库、JSON 包、ORM 框架)自动读写的数据字段,<strong>必须是导出字段(首字母大写)</strong>。这是 Go 语言设计的基本约束,而非 MongoDB 特定问题。养成结构体字段命名遵循 CamelCase 并配合适当 bson/json 标签的习惯,是构建健壮数据层的关键基础。</p>











