gpt4 book ai didi

pointers - 将 uintptr 从反射转换为指针 (*)

转载 作者:数据小太阳 更新时间:2023-10-29 03:23:48 24 4
gpt4 key购买 nike

我只是找不到获取指向给定结构的每个属性的指针片段的方法。我正在使用反射来获取我的指示(感谢 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: Scan error on column index 0: destination not a pointer

我知道这是因为它不是一个好的类型,因为它是一个 uintptr,但是如何将它转换成可用的指针呢?

谢谢

最佳答案

使用unsafe.Pointer将 uintptr 转换为某种类型的指针。例如,以下表达式将 uintptr u 转换为 T 指针:

(*T)(unsafe.Pointer(u))

此转换在 StructAttributesToPointersSlice 中没有帮助,因为结构字段可以是任何类型。此外,不需要从 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
}

关于这段代码的一些说明:

  • 参数必须是指向结构的指针。
  • 无需在字段上调用 ​​CanAddr。检查指向结构的指针涵盖了这一点。
  • CanSet() 跳过未导出的字段。您可能希望它发生 panic 。
  • 函数因调用者的错误而 panic 。考虑改为返回错误。

playground example

关于pointers - 将 uintptr 从反射转换为指针 (*),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47859348/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com