2015-03-21 3 views
2

Я пытаюсь сделать функцию, которая преобразует структуру в способ mysql rows.Scan нуждается в ней, поэтому мне не нужно вручную передавать множество параметров.golang отражать, получить указатель на значение поля struct

Примечание: Я знаю существование sqlx и альтернативу записи вручную в отдельных строках каждого указателя, но я бы хотел решить его таким образом, когда я учусь и хочу понять, что происходит.

Я получаю ошибку с этим решением является:
panic: sql: Scan error on column index 0: destination not a pointer для меня выглядит как valueField.Addr().Pointer() должен быть указатель на значение. Ниже приводится упрощение моего кода.

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

    } 
} 

ответ

4

Вы должны использовать .Interface() не .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 
} 

Причина в том, что, что .Pointer() возвращает действительный «указатель» на данные, вы не можете сделать много с ним без использования unsafe пакет.

Смежные вопросы