空接口类型断言并创建副本



无法弄清楚如何修改作为指针传递给接受空接口的函数的结构类型变量

我正在创建一种通过官方go驱动程序与MongoDB数据库一起使用的库。我正在传递一个结构指针,然后用来自数据库(MongoDBcursor.Decode)的数据填充。这适用于单个文档,但是当我尝试返回文档数组时,只有父文档是正确的,但数组中所有元素的子项(嵌入)保持不变(可能是存储引用而不是实际值)。

实际代码:

// passing model pointer to search function
result, _ := mongodb.Search(&store.Time{}, 
mongodb.D{mongodb.E("transdate", 
mongodb.D{mongodb.E("$gte", timeSearch.DateFrom), mongodb.E("$lte", timeSearch.DateTo)})})
...
func Search(model interface{}, filter interface{}) (result ModelCollection, err error) {
collection := Database.Collection(resolveCollectionName(model))
var cursor *mongo.Cursor
cursor, err = collection.Find(Context, filter)
if err != nil {
log.Fatal(err)
} 
for cursor.Next(Context) {
if err := cursor.Decode(model); err != nil {
log.Fatal(err)
}
modelDeref := reflect.ValueOf(model).Elem().Interface()
result = append(result, modelDeref)
}
return
}

这是我能想到的最接近的游乐场例子。我用自己的解码函数替换了MongoDBcursor.Decode(),但这甚至没有更新父属性。孩子们保持不变

https://play.golang.org/p/lswJJY0yl80

预期:

result:[{A:1 Children:[{B:11}]} {

A:2 Children:[{B:22}]}]

实际:

result:[{A:init Children:[{B:22}]} {

A:init Children:[{B:22}]}]

您正在解码为相同的指针,因此您最终将始终得到一个包含元素的切片,其值与您上次解码的值相同。

相反,您应该在每次迭代中初始化模型类型的新实例,然后解码为该实例。

result, _ := mongodb.Search(store.Time{}, ...) // pass in non-pointer type to make life easier
// ...
func Search(model interface{}, filter interface{}) (result ModelCollection, err error) {
collection := Database.Collection(resolveCollectionName(model))
var cursor *mongo.Cursor
cursor, err = collection.Find(Context, filter)
if err != nil {
log.Fatal(err)
} 
for cursor.Next(Context) {
v := reflect.New(reflect.TypeOf(model)).Interface() // get a new pointer instance
if err := cursor.Decode(v); err != nil { // decode
log.Fatal(err)
}
md := reflect.ValueOf(v).Elem().Interface()
result = append(result, md) // append non-pointer value
}
return
}

最新更新