如何将unsafe.Pointer转换为reflect.Type或reflect.Value

时间:2017-08-30 06:12:49

标签: go

我有一个变量的地址,该类型被转换为unsafe.Pointer,我得到了它的类型名称,例如“int64”或“struct main.Person”或其他。

见代码:

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 个答案:

答案 0 :(得分:1)

为什么需要指针来获取Type?您只需要输入类型名称。

在Go中,无法直接从字符串中获取reflect.Type。必须在某处引用该类型,以便编译器知道它将被包含在内。但是,使用map[string]reflect.Type可以获得相同的效果。

如果你的类型是静态的,只需声明:

var types = map[string]reflect.Type{
    "int64": reflect.TypeOf(int64(0)),
    "string": reflect.TypeOf(string("")),
    // ... and so on
}

如果您的类型是从不同的包动态注册的,您可以从init这样的函数注册您的类型:

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

如果要从指针和类型名称获取reflect.Value,可以执行以下操作:

func ValueOfByAddr(addr unsafe.Pointer, typName string) reflect.Value {
    t, ok := types[typName]
    if !ok {
        panic("Unknown type name")
    }
    return reflect.NewAt(t, addr)
}