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
?为什么不使用*TableMeta
?reflect
的文档说
指针将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
)的指针。
答案 0 :(得分:1)
您拥有的值是指向BookInfo
结构的指针,其类型为*BookInfo
。并且BookInfo.Meta
字段的类型也是一个指针,它的类型为*TableMeta
,因此*BookInfo
可以看作**TableMeta
,因此是“双”指针
的确,struct指针指向其第一个字段,但不要在其上建立。很脆弱。如果在字段之前添加字段,则字段将严重损坏(仅在运行时发生,由于软件包unsafe
而没有编译时消息)。
因此,如果值的类型为*BookInfo
,只需从reflect.Value
包装器中获取该值,就可以像value.Meta
那样引用其字段,其类型为{{ 1}}。避免使用软件包*TableMeta
,尤其是在不需要它的情况下。