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

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!