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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.