0

I'm trying to do something to bring the SQL results dynamically structure, basically I want to run a function by passing the rows and the structure(to get the data type and make one) and return in interface array.

Anyone know how I can do?

I dont want pass the direct "User" struct as param.. that is not dynamically

type User struct{
   Id_user int `json:"id_user"`
   Name string `json:"name"`
   Email string `json:"email"`
   Username string `json: "username"`
}

func main() {
  var user User
  rows, _ := db.Query("SELECT id_user, name, email, username FROM users")
  json.NewEncoder(w).Encode(StructRow(user, rows)) 
}

func StructRow(u interface{}, rows *sql.Rows)[]interface{}{
   var data []interface{}
   for rows.Next() {

      //How i can create a "user" here, dynamically
      //for Example
      //var user reflect.TypeOf(u)

      _ = rows.Scan(StrutForScan(&user)...)
      data = append(data, user)
   }
   return data
}

func StrutForScan(u interface{}) []interface{} {
   val := reflect.ValueOf(u).Elem()
   v := make([]interface{}, val.NumField())
   for i := 0; i < val.NumField(); i++ {
      valueField := val.Field(i)
      v[i] = valueField.Addr().Interface()
   }
   return v
}
3
  • I think an ORM might help you out. Commented Jun 14, 2016 at 18:35
  • Why are you insisting on custom-building a new interface for storing the value? Is it just that you want to have a method that scans the rows without having to know what the destination type is? Might be worth checking out sqlx, it adds a couple additional methods to the db that let you directly scan into structures instead of having to provide each field explicitly or a slice. With that, your scan function only needs to accept an interface and pass it blindly to db.Select() or db.Get(). Commented Jun 14, 2016 at 18:43
  • ohh, well, thanks. Commented Jun 14, 2016 at 19:05

1 Answer 1

1

Changing your function StructRow to

 func StructRow(u interface{}, rows *sql.Rows) []interface{} {
    var data []interface{}
    for rows.Next() {

         t := reflect.TypeOf(u)
         val := reflect.New(t).Interface()

         errScan := rows.Scan(StrutForScan(val)...)
         if errScan != nil {
             //proper err handling
         }
         data = append(data, val)
    }
    return data
 }

will fix it. I guess. For more on reflect package go to: https://golang.org/pkg/reflect/

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks :) You know how i can combine StructRow and StructForScan in the same function?
I think the method that you implemented is pretty straight forward :) . Also as stated in comments above, have a look at github.com/jmoiron/sqlx . I also did. It is pretty awesome.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.