Go 和 MongoDB:通用 DAO 实现问题
Go and MongoDB: generic DAO implementation issue
在当前项目中,我们使用 Go 和 MongoDB 通过 mgo 驱动程序。
对于每个实体,我们必须为 CRUD 操作实现 DAO,它基本上是复制粘贴,例如
func (thisDao ClusterDao) FindAll() ([]*entity.User, error) {
session, collection := thisDao.getCollection()
defer session.Close()
result := []*entity.User{} //create a new empty slice to return
q := bson.M{}
err := collection.Find(q).All(&result)
return result, err
}
对于所有其他实体,除了结果类型外都是一样的。
既然 Go 没有泛型,我们如何避免代码重复?
我尝试传递 result interface{}
参数而不是在方法中创建它,并像这样调用方法:
dao.FindAll([]*entity.User{})
但是 collection.Find().All()
方法需要一个切片作为输入,而不仅仅是接口:
[restful] recover from panic situation: - result argument must be a slice address
/usr/local/go/src/runtime/asm_amd64.s:514
/usr/local/go/src/runtime/panic.go:489
/home/dds/gopath/src/gopkg.in/mgo.v2/session.go:3791
/home/dds/gopath/src/gopkg.in/mgo.v2/session.go:3818
然后我试着让这个参数result []interface{}
,但是那样的话就不可能通过[]*entity.User{}
:
cannot use []*entity.User literal (type []*entity.User) as type []interface {} in argument to thisDao.GenericDao.FindAll
知道如何在 Go 中实现通用 DAO 吗?
您应该能够将 result interface{}
传递给您的 FindAll
函数,并将其传递给 mgo 的 Query.All 方法,因为参数的类型相同。
func (thisDao ClusterDao) FindAll(result interface{}) error {
session, collection := thisDao.getCollection()
defer session.Close()
q := bson.M{}
// just pass result as is, don't do & here
// because that would be a pointer to the interface not
// to the underlying slice, which mgo probably doesn't like
return collection.Find(q).All(result)
}
// ...
users := []*entity.User{}
if err := dao.FindAll(&users); err != nil { // pass pointer to slice here
panic(err)
}
log.Println(users)
在当前项目中,我们使用 Go 和 MongoDB 通过 mgo 驱动程序。 对于每个实体,我们必须为 CRUD 操作实现 DAO,它基本上是复制粘贴,例如
func (thisDao ClusterDao) FindAll() ([]*entity.User, error) {
session, collection := thisDao.getCollection()
defer session.Close()
result := []*entity.User{} //create a new empty slice to return
q := bson.M{}
err := collection.Find(q).All(&result)
return result, err
}
对于所有其他实体,除了结果类型外都是一样的。
既然 Go 没有泛型,我们如何避免代码重复?
我尝试传递 result interface{}
参数而不是在方法中创建它,并像这样调用方法:
dao.FindAll([]*entity.User{})
但是 collection.Find().All()
方法需要一个切片作为输入,而不仅仅是接口:
[restful] recover from panic situation: - result argument must be a slice address
/usr/local/go/src/runtime/asm_amd64.s:514
/usr/local/go/src/runtime/panic.go:489
/home/dds/gopath/src/gopkg.in/mgo.v2/session.go:3791
/home/dds/gopath/src/gopkg.in/mgo.v2/session.go:3818
然后我试着让这个参数result []interface{}
,但是那样的话就不可能通过[]*entity.User{}
:
cannot use []*entity.User literal (type []*entity.User) as type []interface {} in argument to thisDao.GenericDao.FindAll
知道如何在 Go 中实现通用 DAO 吗?
您应该能够将 result interface{}
传递给您的 FindAll
函数,并将其传递给 mgo 的 Query.All 方法,因为参数的类型相同。
func (thisDao ClusterDao) FindAll(result interface{}) error {
session, collection := thisDao.getCollection()
defer session.Close()
q := bson.M{}
// just pass result as is, don't do & here
// because that would be a pointer to the interface not
// to the underlying slice, which mgo probably doesn't like
return collection.Find(q).All(result)
}
// ...
users := []*entity.User{}
if err := dao.FindAll(&users); err != nil { // pass pointer to slice here
panic(err)
}
log.Println(users)