从指针接口获取结构体的大小

Joe*_*oel 2 go

我试图从接口中获取任何结构的大小。这对于按值传递的对象效果很好,但我不知道如何在使用接口传递引用时获取对象的大小。

这是一个表明我遇到的问题的示例: 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)
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

expected size 50
valueObject size [8 12 50 12 0 0 0 0]
referenceObject size [8 12 4 12 12 12 12 8]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当使用按值传递时,我可以获取对象的大小reflect.TypeOf(valueObject).Size(),但是当我按引用传递时,没有任何东西可以给我正确的大小。

Jim*_*imB 6

Go 中没有“引用”类型,指针是一个与其他值一样的值,当然你可以获取指针本身的大小。您还混淆了reflect.Valueinterface{}和您想要的实际值的大小。造成这种混乱的原因是该包unsafe很特殊,并且不采用接口值,而是可以直接采用任何值,这由编译器正确处理。

您可以使用单独的调用来处理指针和结构,或者检查是否有指针并调用Elem()

// struct
reflect.ValueOf(i).Type().Size()
// pointer
reflect.ValueOf(i).Elem().Type().Size()
Run Code Online (Sandbox Code Playgroud)

但是,由于可选地取消引用指针非常常见,因此您可以reflect.Indirect同时处理这两种类型:

reflect.Indirect(reflect.ValueOf(i)).Type().Size()
Run Code Online (Sandbox Code Playgroud)

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())),
Run Code Online (Sandbox Code Playgroud)