download12749 2017-04-03 18:31
浏览 114
已采纳

Go和MongoDB:通用DAO实施问题

In the current project we use Go and MongoDB via mgo driver. For every entity we have to implement DAO for CRUD operations, and it's basically copy-paste, e.g.

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
}

For every other entity it's all the same but the result type.

Since Go has no generics, how could we avoid code duplication?

I've tried to pass the result interface{} param instead of creating it in the method, and call the method like this:

dao.FindAll([]*entity.User{})

but the collection.Find().All() method need a slice as the input, not just interface:

[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

Then I tried to make this param result []interface{}, but in that case it's impossible to pass []*entity.User{}:

cannot use []*entity.User literal (type []*entity.User) as type []interface {} in argument to thisDao.GenericDao.FindAll

Any idea how could I implement generic DAO in Go?

  • 写回答

1条回答 默认 最新

  • dqxyh48864 2017-04-03 19:22
    关注

    You should be able to pass a result interface{} to your FindAll function and just pass it along to mgo's Query.All method since the argument's would have the same type.

    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)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?