简体   繁体   中英

Get size of struct from pointer interface

I am attempting to generically get the size of any struct from an interface. This works fine with objects that are passed by value, but I can't figure out how to get the size of the object when it's passed the reference using an interface.

Here's an example indicating the problem I'm having: 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)
}

This is the output:

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

As you can see, I can get the size of the object when it's passed-by-value using reflect.TypeOf(valueObject).Size() , but nothing gives me the correct size when I pass-by-reference.

There is no "reference" type in go, a pointer is a value like any other, and you can of course get the size of the pointer itself. You also are confusing the reflect.Value , the interface{} and the actual value you want the size of. Contributing to this confusion is that the package unsafe is special, and doesn't take an interface value, rather it can take any value directly, which is properly handled by the compiler.

You could handle the pointer and the struct each with a separate call, or check whether you have a pointer and call Elem() :

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

However, since optionally dereferencing a pointer is quite common, you can use reflect.Indirect to handle both types at once:

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

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

For reference, a description of what some the attempts are actually taking:

// 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())),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM