How to convert unsafe.Pointer to reflect.Type or reflect.Value

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

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)
}

huangapple
  • 本文由 发表于 2017年8月30日 14:12:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/45953170.html
匿名

发表评论

匿名网友

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

确定