我正在尝试从接口一般获取任何结构的大小。这对于按值传递的对象很好用,但是当使用接口传递引用时,我无法弄清楚如何获得对象的大小。
这是一个说明我遇到的问题的示例: 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()
对对象进行值传递时,我可以获得对象的大小,但对引用进行传递时,没有任何东西可以给我正确的大小。
答案 0 :(得分:4)
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())),