Вот решение с использованием отражающего пакета . Вызовите функцию с указателем на срез.
func GetAll(query string, dest interface{}) error {
// Return error if dest is not a pointer to a slice.
slice := reflect.ValueOf(dest)
if slice.Kind() != reflect.Ptr {
return errors.New("dest must be pointer")
}
slice = slice.Elem()
if slice.Kind() != reflect.Slice {
return errors.New("dest must be pointer to struct")
}
rows, err := db.Query(query)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
// Create a new slice element. The variable elementp holds a
// pointer to the new element.
elementp := reflect.New(slice.Type().Elem())
err := rows.Scan(elementp.Interface())
if err != nil {
return err
}
// Append the element to the slice.
slice.Set(reflect.Append(slice, elementp.Elem()))
}
return nil
}
Приведенный выше код работает со стандартным пакетом database / sql, когда результат запроса имеет один столбец, а dest является указателем на фрагмент типа, подходящего для этого столбца. Вот пример:
var names []string
if err := GetAll(db, "select name from people", &names); err != nil {
// handle error
}
Этот код также должен работать с пакетом базы данных, который поддерживает сканирование нескольких столбцов в структуру.