简体   繁体   English

通用 function 以获取 Go 中任何结构的大小

[英]generic function to get size of any structure in Go

I am writing a generic function to get the size of any type of structure, similar to sizeof function in C.我正在编写一个通用的 function 来获取任何类型结构的大小,类似于 C 中的sizeof function。

I am trying to do this using interfaces and reflection but I'm not able to get the correct result.我正在尝试使用接口和反射来做到这一点,但我无法获得正确的结果。 Code is below:代码如下:

 package main import ( "fmt" "reflect" "unsafe" ) func main() { type myType struct { a int b int64 c float32 d float64 e float64 } info:= myType{1, 2, 3.0, 4.0, 5.0} getSize(info) } func getSize(T interface{}) { v:= reflect.ValueOf(T) const size = unsafe.Sizeof(v) fmt.Println(size) }

This code returns wrong result as 12. I am very new to Go, kindly help me on this.此代码返回错误结果为 12。我对 Go 很陌生,请帮助我。

You're getting the size of the reflect.Value struct, not of the object contained in the interface T .您将获得 reflect.Value 结构的大小,而不是接口T中包含的reflect.Value的大小。 Fortunately, reflect.Type has a Size() method:幸运的是, reflect.Type有一个Size()方法:

 size:= reflect.TypeOf(T).Size()

This gives me 40, which makes sense because of padding.这给了我 40,这是有道理的,因为有填充。

Go 1.18 Go 1.18

With Go 1.18 you can use a generic function with unsafe.Sizeof :使用 Go 1.18,您可以使用带有 unsafe.Sizeof 的通用unsafe.Sizeof

 func getSize[T any]() uintptr { var v T return unsafe.Sizeof(v) }

Note that this will be more performant than using reflect , but it will introduce unsafe in your code base — some static analysis tools may give warnings about that.请注意,这将比使用reflect更高效,但它会在您的代码库中引入unsafe ——一些 static 分析工具可能会对此发出警告。

However if your goal is to improve code reuse or get sizes at run time (read on for the solution to that), this won't help much because you still need to call the function with proper instantiation:但是,如果您的目标是提高代码重用或在运行时获取大小(请继续阅读以获取解决方案),这将无济于事,因为您仍然需要使用适当的实例化调用 function:

 type myType struct { a int b int64 c float32 d float64 e float64 } func main() { fmt.Println(getSize[myType]()) }

You might get the most out of this when used as part of some other generic code, eg a generic type or function where you pass a type param into getSize .当用作其他一些泛型代码的一部分时,您可能会充分利用这一点,例如泛型类型或 function ,其中您将类型参数传递给getSize Although if you have the argument v this is equivalent to calling unsafe.Sizeof(v) directly.虽然如果你有参数v这相当于直接调用unsafe.Sizeof(v) Using a function could be still useful to hide usage of unsafe .使用 function 可能仍然有助于隐藏unsafe的使用。 A trivial example:一个简单的例子:

 func printSize[T any](v T) { // (doing something with v) // instantiate with T and call s:= getSize[T]() // s:= unsafe.Sizeof(v) fmt.Println(s) }

Otherwise you can pass an actual argument to getSize .否则,您可以将实际参数传递给getSize Then type inference will make it unnecessary to specify the type param.然后类型推断将不需要指定类型参数。 This code perhaps is more flexible and allows you to pass arbitrary arguments at runtime, while keeping the benefits of avoiding reflection:这段代码可能更灵活,允许您在运行时传递任意 arguments,同时保持避免反射的好处:

 func getSize[T any](v T) uintptr { return unsafe.Sizeof(v) } func main() { type myType struct { a int b int64 c float32 d float64 e float64 } info:= myType{1, 2, 3.0, 4.0, 5.0} // inferred type params fmt.Println(getSize(info)) // 40 fmt.Println(getSize(5.0)) // 8 fmt.Println(getSize([]string{})) // 24 fmt.Println(getSize(struct { id uint64 s *string }{})) // 16 }

Playground: https://go.dev/play/p/kfhqYHUwB2S游乐场: https://go.dev/play/p/kfhqYHUwB2S

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM