在GAE/Go中获取结构体的大小。

huangapple go评论85阅读模式
英文:

Getting size of a structure in GAE/Go

问题

我想要获取GAE/Go中结构体的大小。

我阅读了这篇帖子,并编写了以下代码。

import (
    "reflect"
    "unsafe"
)

func GetSize(T interface{}) {
    size := reflect.TypeOf(T).Size()
    return int((*int)(unsafe.Pointer(size)))
}

但是这段代码无法工作,因为GAE不允许导入unsafe包。

在GAE/Go中,我该如何实现这个功能呢?

英文:

I would like to get the size of a structure in GAE/Go.

I read this post and wrote the code as below.

import (
    "reflect"
    "unsafe"
)

func GetSize(T interface{}) {
    size := reflect.TypeOf(T).Size()
    return int((*int)(unsafe.Pointer(size)))
}

But this code does not work because GAE does not allow to import unsafe.

How can I do this in GAE/Go?

答案1

得分: 2

你提出的解决方案不是有效的代码,它有多个错误。

例如,GetSize()没有结果类型,所以你无法返回任何内容。

接下来,你返回的表达式也是语法错误,它试图将*int指针转换为无效的int类型。

你需要先解引用指针,所以正确的语法应该是:

func GetSize(T interface{}) int {
    size := reflect.TypeOf(T).Size()
    return int(*(*int)(unsafe.Pointer(size)))
}

但是,这没有意义。reflect.Type.Size()已经返回了大小(存储给定类型的值所需的字节数),所以没有必要使用unsafe的魔法。可能令人困惑的是,它的返回类型是uintptr,但你可以将其转换为int后直接使用该值。

简单地使用:

func GetSize(v interface{}) int {
    return int(reflect.TypeOf(v).Size())
}

进行测试:

fmt.Println("Size of int:", GetSize(int(0)))
fmt.Println("Size of int64:", GetSize(int64(0)))
fmt.Println("Size of [100]byte:", GetSize([100]byte{}))

输出结果(在Go Playground上尝试):

Size of int: 4
Size of int64: 8
Size of [100]byte: 100

有一件事你不能忘记:这个GetSize()函数不会递归地检查传入值的大小。所以,例如,如果它是一个具有指针字段的结构体,它不会“计算”指向值的大小,只会计算指针字段的大小。

构建一个能够递归计算复杂数据结构总大小的GetSize()函数并不容易,因为存在像map这样的类型。有关详细信息,请参见https://stackoverflow.com/questions/44257522/how-to-get-variable-memory-size-of-variable-in-golang/44258164#44258164

英文:

Your proposed solution is not valid code, it has multiple errors.

For example GetSize() has no result type, so you couldn't return anything.

Next, the expression you return is also a syntax error, it attempts to convert an *int pointer to int which is not valid.

You need to dereference the pointer first, so the correct syntax would be:

func GetSize(T interface{}) int {
	size := reflect.TypeOf(T).Size()
	return int(*(*int)(unsafe.Pointer(size)))
}

But. It makes no sense. reflect.Type.Size() already returns the size (the number of bytes needed to store a value of the given type), so there is no need of that unsafe magic. What may be confusing is that its return type is uintptr, but you may simply use that value after converting it to int for example.

Simply use:

func GetSize(v interface{}) int {
	return int(reflect.TypeOf(v).Size())
}

Testing it:

fmt.Println("Size of int:", GetSize(int(0)))
fmt.Println("Size of int64:", GetSize(int64(0)))
fmt.Println("Size of [100]byte:", GetSize([100]byte{}))

Output (try it on the Go Playground):

Size of int: 4
Size of int64: 8
Size of [100]byte: 100

One thing you must not forget: this GetSize() will not recurisvely examine the size of the passed value. So for example if it's a struct with a pointer field, it will not "count" the size of the pointed value, only the size of the pointer field.

Constructing a GetSize() that recurisvely counts the total size of a complex data structure is non-trivial due to types like map. For details, see https://stackoverflow.com/questions/44257522/how-to-get-variable-memory-size-of-variable-in-golang/44258164#44258164

huangapple
  • 本文由 发表于 2017年6月14日 14:08:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/44536740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定