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 宇视监控服务器无法登录
  • ¥15 PADS Logic 原理图
  • ¥15 PADS Logic 图标
  • ¥15 电脑和power bi环境都是英文如何将日期层次结构转换成英文
  • ¥15 DruidDataSource一直closing
  • ¥20 气象站点数据求取中~
  • ¥15 如何获取APP内弹出的网址链接
  • ¥15 wifi 图标不见了 不知道怎么办 上不了网 变成小地球了
  • ¥50 STM32单片机传感器读取错误
  • ¥50 power BI 从Mysql服务器导入数据,但连接进去后显示表无数据