I have two structs at the moment.
type One struct {
Name string
Age int
ID int
Owner string
}
type Two struct {
ID int
Make string
Bags string
Age int
Owner string
}
These structs map to a table in a DB, I use an interface to provide access to the DB and contents. In this case just a listing of the data in One and Two based on the owner.
type dbInterface interface {
ListOnesByOwner(owner string) ([]*One, error)
LitsTwosByOwner(owner string) ([]*Two, error)
}
The listing functions are the same except for the structs.
func (db *DB) ListOnes(owner string) ([]*One, error) {
ones = make([]*One, 0)
q := db.NewQuery("One").
Filter("Owner =", owner).
Order("Name")
keys, err := db.client.GetAll(q, &ones)
for i, k := range keys {
ones[i].ID = k.ID
}
return ones, nil
}
func (db *DB) ListTwos(owner string) ([]*Two, error) {
twos = make([]*Two, 0)
q := db.NewQuery("Two").
Filter("Owner =", owner).
Order("Name")
keys, err := db.client.GetAll(q, &twos)
for i, k := range keys {
twos[i].ID = k.ID
}
return twos, nil
}
func main() {
ones, err := DB.ListOnesByOwner(user.ID)
twos, err := DB.ListTwosByOwner(user.ID)
}
I'm fairly new to GO, so I'm wondering what is the idiomatic way to reduce the code duplication seen here? If I was to add a couple more structs then it would be unwieldy because the amount of code duplication needed.
Thanks for any help!
Assuming that db.client.GetAll
takes an interface{}
as its second argument, which it appears to, you can in fact DRY it out:
func (db *DB) dryGet(owner, table string, result interface{}) error {
q := db.NewQuery(table).Filter("Owner =", owner).Order("Name")
keys,err := db.client.GetAll(q, &result)
return err
}
Converting the result to a map is a little more difficult because Go lacks generics, and your structs have no methods that could be used to interface them. It's possible but would require, at the least, creating a getID
method on each type, creating a hasID
interface, and then returning a map[int]hasID
, which the caller would then have to cast the values of back to the struct type to access any other fields. Not optimal, but doable. However, the above solution would at least let you eliminate a good portion of duplicate code.