Получить размер структуры из интерфейса указателя - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь получить размер любой структуры из интерфейса. Это прекрасно работает с объектами, которые передаются по значению, но я не могу понять, как получить размер объекта, когда ему передается ссылка с использованием интерфейса.

Вот пример, показывающий мою проблему: https://play.golang.org/p/QXXZm-j7_hZ

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type T struct {
    c [50]byte
}

func main() {
    fmt.Println("Hello, playground")

    var t T
    s := unsafe.Sizeof(t)
    fmt.Println("expected size", s)
    getSize(t, &t)
}

func getSize(valueObject interface{}, referenceObject interface{}) {
    vs := []uintptr{
        unsafe.Sizeof(valueObject),
        unsafe.Sizeof(reflect.ValueOf(valueObject)),
        reflect.TypeOf(valueObject).Size(), // THIS WORKS FOR VALUE
        reflect.TypeOf(reflect.ValueOf(valueObject)).Size(),
        0, //reflect.TypeOf(reflect.ValueOf(valueObject).Elem()).Size(), //EXCEPTION ACCESSING ELEM WITH VALUE
        0, //reflect.TypeOf(reflect.ValueOf(valueObject).Elem()).Size(), //EXCEPTION ACCESSING ELEM WITH VALUE
        0, //unsafe.Sizeof(reflect.ValueOf(valueObject).Elem()), //EXCEPTION ACCESSING ELEM WITH VALUE
        0, //unsafe.Sizeof(reflect.TypeOf(reflect.ValueOf(valueObject).Elem())), //EXCEPTION ACCESSING ELEM WITH VALUE
    }
    fmt.Println("valueObject size", vs)

    rs := []uintptr{
        unsafe.Sizeof(referenceObject),
        unsafe.Sizeof(reflect.ValueOf(referenceObject)),
        reflect.TypeOf(referenceObject).Size(),
        reflect.TypeOf(reflect.ValueOf(referenceObject)).Size(),
        reflect.TypeOf(reflect.ValueOf(referenceObject).Elem()).Size(),
        reflect.TypeOf(reflect.ValueOf(referenceObject).Elem()).Size(),
        unsafe.Sizeof(reflect.ValueOf(referenceObject).Elem()),
        unsafe.Sizeof(reflect.TypeOf(reflect.ValueOf(referenceObject).Elem())),
    }

    fmt.Println("referenceObject size", rs)
}

Это вывод:

expected size 50
valueObject size [8 12 50 12 0 0 0 0]
referenceObject size [8 12 4 12 12 12 12 8]

Как видите, я могу получить размер объекта, когда он передается по значению, используя reflect.TypeOf(valueObject).Size(), но ничто не дает мне правильный размер, когда я передаю по ссылке.

1 Ответ

4 голосов
/ 17 мая 2019

В go нет «ссылочного» типа, указатель является значением, аналогичным любому другому, и вы, конечно, можете получить размер самого указателя.Вы также путаете reflect.Value, interface{} и фактическое значение, размер которого вы хотите.Этой путанице способствует то, что пакет unsafe является специальным и не принимает значения интерфейса, скорее он может принимать любое значение напрямую, что правильно обрабатывается компилятором.

Вы можете обработать указательи каждая структура имеет отдельный вызов, или проверьте, есть ли у вас указатель и вызов Elem():

// struct
reflect.ValueOf(i).Type().Size()
// pointer
reflect.ValueOf(i).Elem().Type().Size()

Однако, поскольку необязательное разыменование указателя довольно распространено, вы можете использовать reflect.Indirect для обработкиоба типа одновременно:

reflect.Indirect(reflect.ValueOf(i)).Type().Size()

https://play.golang.org/p/og-uMDXCmEr

Для справки, описание того, что на самом деле предпринимаются некоторые попытки:

// size of the interface value
unsafe.Sizeof(valueObject)

// size of reflect.Value
unsafe.Sizeof(reflect.ValueOf(valueObject))

// size of the reflect.Value type 
reflect.TypeOf(reflect.ValueOf(valueObject)).Size()

// size of the interface value
unsafe.Sizeof(referenceObject)

// size of the reflect.Value
unsafe.Sizeof(reflect.ValueOf(referenceObject))

// size of the pointer value
reflect.TypeOf(referenceObject).Size()

// size of the reflect.Value type
reflect.TypeOf(reflect.ValueOf(referenceObject)).Size(),

// size of the of reflect.Value type again
reflect.TypeOf(reflect.ValueOf(referenceObject).Elem()).Size()

// size of the reflect.Value
unsafe.Sizeof(reflect.ValueOf(referenceObject).Elem()),

// size of the reflect.Type interface value
unsafe.Sizeof(reflect.TypeOf(reflect.ValueOf(referenceObject).Elem())),
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...