通过使用接口从数据库中检索数据

huangapple go评论89阅读模式
英文:

Retrieve from database via mgo using interface

问题

我有以下(未经测试的)函数:

func Execute(task MyInterface) {
    db := session.DB(task.Database()).C(task.Collection())
    var tasks []MyInterface
    db.Find(nil).All(&tasks)
    for _, t := range tasks { t.Do() }
}

我想给我的函数一个实现了接口MyInterface的结构体。然后它应该从mongodb中检索一些值,并调用检索到的结构体上的一个方法。

问题是错误:reflect.Set:类型为bson.M的值无法分配给类型mypkg.MyInterface - 有没有办法让它工作?我尝试使用原始结构体的类型来实例化tasks,但无法使其工作。

任何帮助将不胜感激 - 谢谢 通过使用接口从数据库中检索数据

英文:

I have following (untested) function:

func Execute(task MyInterface) {
    db := session.DB(task.Database()).C(task.Collection())
    var tasks []MyInterface
    db.Find(nil).All(&tasks)
    for _, t := range tasks { t.Do() }
}

I want to give my function a struct that implements interface MyInterface. It should then retrieve some values from mongodb and call a method on the retrieved structs.

Problem is error: reflect.Set: value of type bson.M is not assignable to type mypkg.MyInterface - is there some way to make this work? I tried to instantiate tasks using the type of the original struct, but couldn't get it working.

Any help would be appreciated - thanks 通过使用接口从数据库中检索数据

答案1

得分: 1

mgo无法创建MyInterface对象,因为MyInterface只是一个接口。尝试这样做:

myObject := &MyInterface{}  //失败

我认为这基本上是mgo尝试为每个要解组的记录所做的操作。

要实现你想要的效果,将tasks定义为[]map[string]interface{}[]bson.M类型,然后:

for _, o := range tasks {
    t := &MyTypeThatImplementsMyInterface{ 
        Field1 : o["my_field"],
        //等等  
    } 
    t.Do()
}

要么将tasks定义为一个实现MyInterface的类型的切片(var tasks []MyStructType),并且其字段与数据库中的bson对象的键和值类型匹配。如果存储的数据是多个实现MyInterface的类型,则可能无法正常工作,因此上面的切片和映射选项要小心。

此外,对于Find(nil).All(&tasks)要小心。如果该集合中有数百万条记录,并且记录的大小较大,可能会导致内存不足。

英文:

mgo can't create MyInterface objects since MyInterface is just an interface. Try doing :

myObject := &MyInterface{}  //fails

I think it's basically what mgo is trying to do for each record it tries to unmarshal.

To achieve what you want, make tasks of type []map[string]interface{} or []bson.M (the latter is an alias for the former) and then:

for _, o := range tasks {
    t := &MyTypeThatImplementsMyInterface{ 
        Field1 : o["my_field"],
        //etc.  
    } 
    t.Do()
}

Either that or make tasks a slice of objects of a type (var tasks []MyStructType) that implements MyInterface and that its fields match the keys and values types of your bson objects in your database. That might not work if your stored data is of more than one type implementing MyInterface, hence the slice of maps option above.

Also, be cautious with Find(nil).All(&tasks). If you have millions of records in that collection, depending on the records size, you may fall short of memory.

huangapple
  • 本文由 发表于 2013年2月21日 22:03:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/15004200.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定