我无法找到获取给定结构的每个属性的指针片段的方法。我正在使用反射来获取指针(感谢https://stackoverflow.com/a/24348352/6093604)
if valueField.CanAddr() {
address = fmt.Sprintf("0x%X", valueField.Addr().Pointer())
}
正如你所看到的,valueField.Addr()。Pointer()返回一个指针addr值,但是,使用反射,我希望获得sql.Rows.Scan()
的可用指针
所以我做的是:
func StructAttributesToPointersSlice(object interface{}) []interface{} {
val := reflect.ValueOf(object)
if val.Kind() == reflect.Interface && !val.IsNil() {
elm := val.Elem()
if elm.Kind() == reflect.Ptr && !elm.IsNil() && elm.Elem().Kind() == reflect.Ptr {
val = elm
}
}
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
var ptrs []interface{}
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
if valueField.Kind() == reflect.Ptr {
valueField = valueField.Elem()
}
if valueField.CanAddr() {
ptrs = append(ptrs, valueField.Addr().Pointer())
}
}
return ptrs
}
但是当我尝试将它用于Scan()
sql函数时:
var values []interface{}
// Iterate over each rows got from the query
for rows.Next() {
ptrs := utils.StructAttributesToPointersSlice(&newObject)
for _, item := range ptrs {
fmt.Println(reflect.TypeOf(item))
}
err = rows.Scan(ptrs...)
if err != nil {
return nil, model.Status{Code: http.StatusInternalServerError, Error: err.Error()}
} else {
values = append(values, newObject)
}
}
我收到此错误:
sql:列索引0上的扫描错误:目标不是指针
我知道它是因为它不是好类型,因为它是uintptr
,但是如何将它转换为可用的指针?
由于
答案 0 :(得分:0)
使用unsafe.Pointer将uintptr转换为某种类型的指针。例如,以下表达式将uintptr u
转换为T
指针:
(*T)(unsafe.Pointer(u))
此转换在StructAttributesToPointersSlice
中没有帮助,因为struct字段可以是任何类型。此外,不需要uintptr
的转换,也不安全。
表达式valueField.Addr()
是指向字段的指针的reflect.Value。调用Interface()
以获取实际指针。要修复该程序,请更改
ptrs = append(ptrs, valueField.Addr().Pointer())
到
ptrs = append(ptrs, valueField.Addr().Interface())
以下是该功能的简化版本:
func StructAttributesToPointersSlice(object interface{}) []interface{} {
v := reflect.ValueOf(object)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
panic("argument must be a pointer to struct")
}
v = v.Elem()
var result []interface{}
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
if !f.CanSet() {
continue
}
result = append(result, f.Addr().Interface())
}
return result
}
关于此代码的一些注意事项: