HiveBrain v1.2.0
Get Started
← Back to all entries
patterngoMinor

MongoDB CRUD operations for various types of data in Go

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
operationsmongodbfortypesdatavariouscrud

Problem

First of all I am a newbie in Go. I wrote a CRUD REST API that consists of handlers, a database layer and so on, and it contains a lot of code duplication. I see some patterns here, and I know how to reuse code in some other languages like JS or Java using generics or dynamic types.

What are my options in Go? Note that I don't want to use interface{}.

Here is my userdb CRUD set of function that create, update and so on.

package userdb

import (
    "github.com/atsman/interviewr-go/models"
    "github.com/op/go-logging"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)

var log = logging.MustGetLogger("db.user")

func GetUserC(db *mgo.Database) *mgo.Collection {
    return db.C(models.CollectionUsers)
}

func Create(db *mgo.Database, user *models.User) error {
    return GetUserC(db).Insert(user)
}

func Update(db *mgo.Database, id *bson.ObjectId, user *map[string]interface{}) (error, *models.User) {
    var updatedUser = models.User{}
    err := GetUserC(db).UpdateId(id, bson.M{
        "$set": user,
    })
    if err != nil {
        return err, &updatedUser
    }

    err = GetUserC(db).FindId(id).One(&updatedUser)
    return err, &updatedUser
}

func List(db *mgo.Database, query *bson.M) (error, *[]models.User) {
    var users []models.User
    err := GetUserC(db).Find(bson.M{}).All(&users)
    return err, &users
}

func Delete(db *mgo.Database, id *bson.ObjectId) (error, *models.User) {
    var user = models.User{}
    err := GetUserC(db).FindId(id).One(&user)
    if err != nil {
        return err, &user
    }

    err = GetUserC(db).RemoveId(id)
    if err != nil {
        return err, &user
    }

    return nil, &user
}


And here is my companydb package. Its goals are almost the same except with the Company model.

```
package companydb

import (
"github.com/atsman/interviewr-go/models"
"github.com/op/go-logging"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)

var log = logging.MustGetLogger("db.company")

func GetCompanyC(db *

Solution

I am also starting out in go (although I used GAE's Datastore), and have spent some time thinking about this. I considered 3 options:
1 Code Generation

I think code generation would be a solid way to approach this solution. There's even a library starting out called streetCURD for PostgreSQL.
Code generation seems like a common way to do things in go. There is also a golang code generation tool called gen.
2 Don't Generalize

Depending on how many times you will copy and paste this, it may not be worth for you to generalize it. However, I find that after a few structs I start doubting this route... and others are not generalizing too: Example1. example2.
3 Interfaces

I ended up using interface{} for somethings (like error checking) which you stated you are not interested in. I felt it made the code more readable, which is my goal.

Looking over your code, it seems like you are interested in a method that return a user or a company- depending in the input, interface{} would be the way to go... (pun not intended).

Since I am just starting out, I'd love to see better responses to this question.

Context

StackExchange Code Review Q#121902, answer score: 3

Revisions (0)

No revisions yet.