
通过将结构体指针作为 interface{} 类型参数传入,可安全复用 mongodb 查询函数,无需反射或类型断言——go 的接口机制天然支持此场景。
在 Go 语言中,interface{} 是最通用的空接口,能接收任意类型的值(包括结构体指针)。关键在于:*当传入 &user(即 `User)时,其底层类型信息完整保留在interface{}值中**。MongoDB 的One()` 方法正是依赖该类型信息,将 BSON 数据正确反序列化到目标结构体字段中。
因此,只需将原函数签名简化为:
func findEntry(db, table string, entry interface{}, finder bson.M) error {
c := mongoSession.DB(db).C(table)
return c.Find(finder).One(entry)
}✅ 正确调用方式(推荐):
var user User
err := findEntry("mydb", "users", &user, bson.M{"email": "alice@example.com"})
if err != nil {
log.Fatal(err)
}
// user 现已填充数据,字段名需与 BSON 键匹配(或通过 `bson` tag 映射)⚠️ 注意事项:
- 必须传入指针(如 &user),否则 One() 无法修改原始变量(Go 按值传递);
- finder 参数应使用 bson.M(值类型),而非 *bson.M —— bson.M 本身是 map[string]interface{} 别名,已具备高效性与可变性,取地址无必要且易引发 nil 指针风险;
- 结构体字段需导出(首字母大写),并建议添加 bson tag 以精确控制序列化/反序列化行为,例如:
type User struct { ID bson.ObjectId `bson:"_id,omitempty"` Name string `bson:"name"` Email string `bson:"email"` }
? 总结:Go 虽无泛型(旧版),但通过 interface{} + 值语义 + 运行时类型保留,已足以支撑此类“类型擦除后安全还原”的典型场景。只要调用方传入正确的结构体指针,函数内部无需任何反射、断言或类型转换,即可实现跨结构体复用,简洁、安全、符合 Go 的惯用法。










