英文:
Get pointer to a struct field value
问题
我正在尝试创建一个函数,将结构体转换为mysql rows.Scan函数所需的方式,这样我就不需要手动传递很多参数。
注意:我知道sqlx的存在以及手动在单独的行中编写每个指针的替代方法,但我想以这种方式解决它,因为我正在学习Go,并且想要理解其中的原理。
我使用这种解决方案时遇到的错误是:
对我来说,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))
}
}
英文:
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:
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))
}
}
答案1
得分: 24
你需要使用.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
包,你无法对其进行太多操作。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论