I've been trying hard (well.. as much as I can considering my lack of 
in-depth go knowledge or - to be perfectly honest - lack of in-depth 
knowledge of anything) to find suitable go+sql technique that would not 
require a lot of code repetition, not use reflection and not use ORMs of 
any sort... Could somebody please tell me if there's anything particularly 
wrong with the following:


type ScannerFunc func() []interface{}

func (db *DB) ScanSome(stmt string, sf ScannerFunc, params ...interface{}) 
error {
 rows, err := db.Query(stmt, params...)
 if err != nil {
 return err
 }
 defer rows.Close()
 for rows.Next() {
 err = rows.Scan(sf()...)
 if err != nil {
 return err
 }
 }
 if err = rows.Err(); err != nil {
 return err
 }
 return nil
}

Having the above I could then implement the following for each of my 
'models' (User being an example below). This could easily be 'go 
generate'-d for each model


type User struct {
    UserID  int64
    Name    string
    Role    int
    // (...)
}

func ScanUsersFunc(users *[]*User) ScannerFunc {
    return ScannerFunc(func() []interface{}) {
        u := User{}
        *users = append(*users, &u)
        var r []interface{} = []interface{}{&u.UserID, &u.Name, &u.Role, (more 
properties)}
        return r
    }
}


and finally use it like this: 


const (
    sqlUsersByRole = "SELECT user_id,name,role, (more if needed) FROM user 
WHERE role=?"
    sqlAllUsers    = "SELECT user_id,name,role FROM user"
)

func (db *DB) UsersByRole(role int) ([]*User, error) {
    users := make([]*User, 0)
    err := db.ScanSome(sqlUsersByRole, ScanUsersFunc(&users), role)
    if err != nil {
        return nil, err
    }
    return users, nil
}

func (db *DB) AllUsers() ([]*User, error) {
    users := make([]*User, 0)
    err := db.ScanSome(sqlAllUsers, ScanUsersFunc(&users))
    if err != nil {
        return nil, err
    }
    return users, nil
}


Alternatively (to avoid scanning/returning all results) a callback could be 
provided to ScanSome and called after each scan.

Obviously I could also implement ScanOne for situations where I only expect 
one row of results...


So - any obvious issues with the above 'technique'...?


Thanks,

adam



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to