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
)的指针。 最佳答案
您拥有的值是BookInfo
结构的指针,类型为*BookInfo
。并且BookInfo.Meta
字段的类型也是一个指针,它的类型为*TableMeta
,因此可以将*BookInfo
视为**TableMeta
,因此是“双”指针。
的确,struct指针指向其第一个字段,但不要在此字段上构建。很脆弱。如果在它之前添加一个字段,它将严重损坏(这只会在运行时发生,由于软件包unsafe
而不会产生编译时消息)。
因此,如果该值的类型为*BookInfo
,只需从reflect.Value
包装器中获取该值,则可以像value.Meta
一样引用其字段,该字段将为*TableMeta
类型。避免使用unsafe
包,尤其是在不需要时。