refle.Pointer () возвращаемое значение не является адресом значения - PullRequest
0 голосов
/ 05 ноября 2018
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 вместо unsafe.Pointer, чтобы код, использующий отражение, не мог получить unsafe. Указывает без явного импорта небезопасного пакета. Это паникует, если v Kind не Чан, Func, Map, Ptr, Slice или UnsafePointer.

На мой взгляд:

info := &BookInfo{}
val := reflect.ValueOf(info)
ptr := val.Pointer()
meta := (*TableMeta)(unsafe.Pointer(val.Pointer()))

должно работать, но, на самом деле, когда я позвонил val.Pointer(), возвращаемое значение является указателем *TableMeta (**TableMeta).

1 Ответ

0 голосов
/ 05 ноября 2018

У вас есть указатель на структуру BookInfo, тип *BookInfo. И тип поля BookInfo.Meta также является указателем, он имеет тип *TableMeta, таким образом, *BookInfo можно рассматривать как **TableMeta, следовательно, "двойной" указатель.

Это правда, что указатель структуры указывает на свое первое поле, но не опирается на него. Это хрупкое. Если вы добавите поле перед ним, оно будет плохо работать (что произойдет только во время выполнения, без сообщений во время компиляции из-за пакета unsafe).

Так что, если значение имеет тип *BookInfo, просто получите его из оболочки reflect.Value, тогда вы можете ссылаться на его поле как value.Meta, которое будет иметь тип *TableMeta. Не используйте пакет unsafe, особенно если он не нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...