I'm trying to make a function that converts a struct in the way mysql rows.Scan function needs it, so I don't need to pass manually lots of parameters.
Note: I know the existence of sqlx and the alternative of writing manually in separate lines every pointer, but I'd like to solve it in this way as I'm learning go and want to understand what's going on.
The error I get with this solution is:panic: sql: Scan error on column index 0: destination not a pointer
to me looks like valueField.Addr().Pointer()
should be a Pointer to the value. The following is a simplification of my code.
type User struct {
Name string
Age int
}
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().Pointer()
}
return v
}
func ListUsers {
rows, err := db.Query("SELECT * FROM users")
PanicIf(err)
var user User
for rows.Next() {
err := rows.Scan(StrutForScan(&user)...)
PanicIf(err)
fmt.Printf("\nName: %s, Age: %s", user.Name, string(user.Age))
}
}
You need to use .Interface()
not .Pointer()
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
}
The reason behind that is that .Pointer()
returns an actual "pointer" to the data, you can't do much with it without using the unsafe
package.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With