英文:
How to get a byte pointer to a value of any data type in Golang?
问题
我已经成功在Go中实现了以下函数。但是我想优化/泛化代码,使得该函数可以返回我传入的任何值的第一个字节的指针。目前它只适用于[]uint32,但我想将其用于获取许多其他类型(如byte[],int[],string等)的起始内存地址作为*byte。
有没有更通用的方法来做到这一点,而不是针对我需要处理的每种类型都编写case语句?
以下是代码的Go Playground链接:https://play.golang.org/p/KtNTbERQGa
package main
import (
"fmt"
"reflect"
"unsafe"
)
func ToBytePointer(data interface{}) *byte {
fmt.Println("Received type is", reflect.TypeOf(data))
switch data.(type) {
case []uint32:
typedData := data.([]uint32)
return (*byte)(unsafe.Pointer(&typedData[0]))
default:
return nil
}
}
func main() {
var data = []uint32{1, 2, 3}
var dataBytePointer = (*byte)(unsafe.Pointer(&data[0]))
fmt.Println(dataBytePointer, ToBytePointer(data))
}
英文:
I've managed to get the following function working in Go. But I want to optimize/generalize the code such that this function would return me a pointer to the first byte of any value I pass into the function. Currently it will only work for []uint32, but I want to use it to get the starting memory address as a *byte for many other types (i.e. byte[], int[], string, etc).
Is there a more generic way to do this rather than catching every single type I need to address as case statements?
Go Playground Link for below code: https://play.golang.org/p/KtNTbERQGa
package main
import (
"fmt"
"reflect"
"unsafe"
)
func ToBytePointer(data interface{}) *byte {
fmt.Println("Received type is", reflect.TypeOf(data))
switch data.(type) {
case []uint32:
typedData := data.([]uint32)
return (*byte)(unsafe.Pointer(&typedData[0]))
default:
return nil
}
}
func main() {
var data = []uint32{1, 2, 3}
var dataBytePointer = (*byte)(unsafe.Pointer(&data[0]))
fmt.Println(dataBytePointer, ToBytePointer(data))
}
答案1
得分: 1
谢谢建议,我相信我已经找到了我要找的东西。这是可以做到的,只需要稍微深入一下Go语言的反射包。我会回答自己的问题,这样其他人也许会觉得有帮助。
在Go语言中,获取任何已分配内存块的起始内存地址作为字节指针的优雅一行代码是:
(*byte)(unsafe.Pointer(reflect.ValueOf(任何已分配的数据放在这里).Pointer()))
如果有人需要检查它对任何数据类型的行为,比如 []uint32、[]byte、string、int、struct,请查看我准备的这个示例PlayGround。
https://play.golang.org/p/G5fUOCfNCS
英文:
Thanks for the suggestions, I believe I've found what I was looking for. It can be done, just needed to dig a little bit into the reflection package of Go. I'll answer my own question just so that somebody else might find this helpful.
The elegant one liner to get the starting memory address of any allocated block of memory as a byte pointer in Go would be:
(*byte)(unsafe.Pointer(reflect.ValueOf(anyAllocatedDataGoesHere).Pointer()))
If anybody needs to check how it will behave for any data type, i.e []uint32, []byte, string, int, struct, have a look at this sample PlayGround I prepared.
答案2
得分: 0
Golang没有泛型,所以我猜你需要处理每一种类型。
另外,在你的示例中,你获取的是切片中第一个元素的第一个字节,而不是传递给函数的值的第一个字节。
英文:
Golang does not have generics, so I guess you need to catch every single type.
Also, in your example, you got the first byte of the first element in the slice, not the first byte of the value passed to the function.
答案3
得分: 0
根据你的应用程序,你可以考虑使用Gob编码或protobuf(在Brad Fitz的groupcache中使用)。你将复制你的数据,我相信底层仍然会进行反射,但至少你会得到经过优化的复制和字节编码,这可能是一个优点,因为我猜想一旦你有了这些字节,你的应用程序下一步可能是进行某种形式的复制。
英文:
Depending on what your application is, you might consider Gob encoding or protobuf (as used in Brad Fitz's groupcache). You'd be making a copy of your data, and I'm pretty sure there's still reflection going on under the hood, but at least you're getting well-optimized copying & byte encoding, which may be a plus since I suspect the next step in your application once you have these bytes is a copy of some sort.
1: https://github.com/golang/groupcache/blob/master/sinks.go "groupcache"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论