【问题标题】:Get size of struct from pointer interface从指针接口获取结构的大小
【发布时间】:2019-05-18 08:45:50
【问题描述】:

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

这是一个示例,说明我遇到的问题: 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() 传递值时,我可以得到对象的大小,但是当我通过引用传递时,我没有得到正确的大小。

【问题讨论】:

    标签: go


    【解决方案1】:

    go 中没有“引用”类型,指针和其他类型一样是一个值,当然你可以获取指针本身的大小。您还混淆了reflect.Valueinterface{} 和您想要大小的实际值。造成这种混乱的是包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())),
    

    【讨论】:

    • 解决了,谢谢详细的解释
    猜你喜欢
    • 1970-01-01
    • 2022-11-30
    • 2014-07-08
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    相关资源
    最近更新 更多