13

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))

    }
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
alfonsodev
  • 2,714
  • 2
  • 23
  • 30

1 Answers1

24

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.

OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • Not part of the question but i'll add this in case anyone searches for it. Getting a int or string (or any type of) pointer is possible. Result of `.Interface()` can be assertable to any pointer type like `Interface().(*int)` or `Interface().(*string)`. – ufukty Mar 01 '23 at 08:47