获取指向结构字段值的指针
Get pointer to a struct field value
我正在尝试制作一个函数,以 mysql rows.Scan 函数需要的方式转换结构,因此我不需要手动传递大量参数。
注意:我知道 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))
}
}
您需要使用 .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()
returns 对数据的实际 "pointer",如果不使用 unsafe
包,您将无法对其做很多事情。
我正在尝试制作一个函数,以 mysql rows.Scan 函数需要的方式转换结构,因此我不需要手动传递大量参数。
注意:我知道 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))
}
}
您需要使用 .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()
returns 对数据的实际 "pointer",如果不使用 unsafe
包,您将无法对其做很多事情。