I had the same line of thinking regarding avoiding an ORM. I settled on using sqlx for my project.
On Friday, June 2, 2017 at 8:55:12 AM UTC-4, brylant wrote: > > > 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.