type BookInfo struct {
    Meta         *TableMeta
    ...
}

func (si *schemaInfo) getTabInfo(obj interface{}) (*tabInfo, error) {
    typ := reflect.TypeOf(obj)
    val := reflect.ValueOf(obj)
    if typ.Kind() != reflect.Ptr {
        return nil, errors.New("nborm.schemaInfo.getDBInfo() error: required a pointer")
    }
    meta := *(**TableMeta)(unsafe.Pointer(val.Pointer()))
    ...
 }
getTabInfo()效果很好,但是我想知道为什么val.Pointer()返回**TableMeta的值?为什么不使用*TableMetareflect的文档说:

指针将v的值作为uintptr返回。它返回uintptr而不是
不安全的指针,以便使用反射的代码无法获得
不安全的指针,而不显式导入不安全的程序包。它
如果v的种类不是Chan,Func,Map,Ptr,Slice或
UnsafePointer。

在我脑海里:
info := &BookInfo{}
val := reflect.ValueOf(info)
ptr := val.Pointer()
meta := (*TableMeta)(unsafe.Pointer(val.Pointer()))

应该可以,但是实际上当我调用val.Pointer()时,返回的值是*TableMeta(**TableMeta)的指针。

最佳答案

您拥有的值是BookInfo结构的指针,类型为*BookInfo。并且BookInfo.Meta字段的类型也是一个指针,它的类型为*TableMeta,因此可以将*BookInfo视为**TableMeta,因此是“双”指针。

的确,struct指针指向其第一个字段,但不要在此字段上构建。很脆弱。如果在它之前添加一个字段,它将严重损坏(这只会在运行时发生,由于软件包unsafe而不会产生编译时消息)。

因此,如果该值的类型为*BookInfo,只需从reflect.Value包装器中获取该值,则可以像value.Meta一样引用其字段,该字段将为*TableMeta类型。避免使用unsafe包,尤其是在不需要时。

09-09 18:17