doupao1978 2019-05-17 19:45
浏览 38
已采纳

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

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.

  • 写回答

1条回答 默认 最新

  • duangutian1426 2019-05-17 19:54
    关注

    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())),
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 CCF-CSP 2023 第三题 解压缩(50%)
  • ¥30 comfyui openpose报错
  • ¥20 Wpf Datarid单元格闪烁效果的实现
  • ¥15 图像分割、图像边缘提取
  • ¥15 sqlserver执行存储过程报错
  • ¥100 nuxt、uniapp、ruoyi-vue 相关发布问题
  • ¥15 浮窗和全屏应用同时存在,全屏应用输入法无法弹出
  • ¥100 matlab2009 32位一直初始化
  • ¥15 Expected type 'str | PathLike[str]…… bytes' instead
  • ¥15 三极管电路求解,已知电阻电压和三级关放大倍数