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

报告相同问题?

悬赏问题

  • ¥20 蓝牙耳机怎么查看日志
  • ¥15 R语言 拟时序分析降维图如何减少分支
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统