英文:
How to convert unsafe.Pointer to reflect.Type or reflect.Value
问题
我得到了一个变量的地址,其类型被转换为unsafe.Pointer
,并且我得到了它的类型名称,例如"int64"或"struct main.Person"或其他类型。
看一下代码:
package main
import (
"reflect"
"unsafe"
)
type Person struct {
Name string
Age int
}
func main() {
p := Person{"john", 25}
addr := unsafe.Pointer(&p)
typName := "struct main.Person"
typ := TypeOfByAddr(addr, typName)
// 现在,在函数module.TypeOfByAddr中,我得到了变量addr和typName
// 如何在不使用package.Person进行转换的情况下获取变量p的reflect.Type?
_ = typ
}
package module
func TypeOfByAddr(addr unsafe.Pointer, typName string) reflect.Type {
// 如何将addr转换为reflect.Type?
return nil
}
英文:
I got one variable's address which type is converted to unsafe.Pointer, and I got its type name, such as "int64" or "struct main.Person" or others.
see the code:
package main
type Person struct {
Name string
Age int
}
p := Person{"john", 25}
addr := unsafe.Pointer(&p)
typName := "struct main.Person"
typ := module.TypeOfByAddr(addr, typName)
// now, I got variable addr, typName in func module.TypeOfByAddr
// how can I get reflect.Type of variable p without using package.Person to convert?
package module
func TypeOfByAddr(addr unsafe.Pointer, typName string) reflect.Type {
// how to convert addr to reflect.Type?
}
答案1
得分: 1
为什么需要指针来获取类型?你只需要类型名称就可以了。
在Go语言中,无法直接通过字符串获取reflect.Type
。编译器需要在某处引用该类型,才能知道它需要被包含。不过,你可以使用map[string]reflect.Type
来达到相同的效果。
如果你的类型是静态的,可以这样声明:
var types = map[string]reflect.Type{
"int64": reflect.TypeOf(int64(0)),
"string": reflect.TypeOf(string("")),
// ... 其他类型
}
如果你的类型是动态注册的,来自不同的包,你可以在init
函数中注册你的类型,像这样:
var types = make(map[string]reflect.Type)
func AddType(name string, i interface{}) {
if _, ok := types[name]; ok {
panic("类型 " + name + " 已经注册多次")
}
types[name] = reflect.TypeOf(i)
}
// 在其他地方调用
func init() {
AddType("struct main.Person", Person{})
}
如果你想通过指针和类型名称获取reflect.Value
,可以使用以下方法:
func ValueOfByAddr(addr unsafe.Pointer, typName string) reflect.Value {
t, ok := types[typName]
if !ok {
panic("未知的类型名称")
}
return reflect.NewAt(t, addr)
}
英文:
Why would you need the pointer to get the Type? All you need is the type name.
In Go, it is not possible to get the reflect.Type
from a string directly. The type must be referenced somewhere in order for the compiler to know it is to be included. However, you can get the same effect using map[string]reflect.Type
.
If your types are static, just declare:
var types = map[string]reflect.Type{
"int64": reflect.TypeOf(int64(0)),
"string": reflect.TypeOf(string("")),
// ... and so on
}
If your types are registered dynamically from different packages, you can register your types from init
functions like this:
var types = make(map[string]reflect.Type)
func AddType(name string, i interface{}) {
if _, ok := types[name]; ok {
panic("Type " + name + " registered multiple times")
}
types[name] = reflect.TypeOf(i)
}
// Called somewhere else
func init() {
AddType("struct main.Person", Person{})
}
If you want to get the reflect.Value
from a pointer and a type name, you can do the following:
func ValueOfByAddr(addr unsafe.Pointer, typName string) reflect.Value {
t, ok := types[typName]
if !ok {
panic("Unknown type name")
}
return reflect.NewAt(t, addr)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论