var id int
var name string
err = rows.Scan(&id, &name)
// or
row = MyStruct{}
err = rows.Scan(&row.Id, &row.Name)
This seemed like a lot of repetition if every query required this logic. My next thought was to see if I could pass in a struct, use reflect to obtain the fields and return a slice of values.
Here are two examples, the first one uses uses append and requires type assertion to access the fields. The second example uses reflect.append and each field can be accessed directly from the element.
Note: Additional checks should be added, such as making sure the address of the object is passed in.
First
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
Id int
Name string
}
func main() {
me := MyStruct{}
result := doIt(&me)
for _, v := range result {
fmt.Printf("%d %s\n", v.(MyStruct).Id, v.(MyStruct).Name)
}
}
func doIt(genericStruct interface{}) []interface{} {
params := []interface{}{}
var myStruct reflect.Value
structType := reflect.TypeOf(genericStruct).Elem()
// First Element
myStruct = reflect.New(structType).Elem()
myStruct.FieldByName("Id").SetInt(1)
myStruct.FieldByName("Name").SetString("one")
fmt.Printf("%#v\n", myStruct)
params = append(params, myStruct.Interface())
// Second Element
myStruct = reflect.New(structType).Elem()
myStruct.FieldByName("Id").SetInt(2)
myStruct.FieldByName("Name").SetString("two")
fmt.Printf("%#v\n", myStruct)
params = append(params, myStruct.Interface())
return params
}
Second
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
Id int
Name string
}
func main() {
myStruct := []MyStruct{}
doIt(&myStruct)
for _, v := range myStruct {
fmt.Printf("%d %s\n", v.Id, v.Name)
}
}
func doIt(genericStructArray interface{}) {
var myStruct reflect.Value
genericValue := reflect.ValueOf(genericStructArray).Elem()
genericType := genericValue.Type().Elem()
// First Element
myStruct = reflect.New(genericType).Elem()
myStruct.FieldByName("Id").SetInt(1)
myStruct.FieldByName("Name").SetString("one")
fmt.Printf("%#v\n", myStruct)
genericValue.Set(reflect.Append(genericValue, myStruct))
// Second Element
myStruct = reflect.New(genericType).Elem()
myStruct.FieldByName("Id").SetInt(2)
myStruct.FieldByName("Name").SetString("two")
fmt.Printf("%#v\n", myStruct)
genericValue.Set(reflect.Append(genericValue, myStruct))
}
Output (same for both)
main.MyStruct{Id:5, Name:"one"}
main.MyStruct{Id:2, Name:"two"}
5 one
2 two