您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何在运行时发现所有包类型?

如何在运行时发现所有包类型?

(请参阅底部的2019更新)

:未经测试且骇客。每当发布新版本的Go时可能会中断。

通过对Go的运行时进行一些修改,可以获得运行时知道的所有类型。在您自己的程序包中包含一个小的程序集文件,其中包含:

TEXT yourpackage·typelinks(SB), NOSPLIT, $0-0
    JMP reflect·typelinks(SB)

在中yourpackage,声明函数原型(无主体):

func typelinks() []*typeDefDummy

除了类型定义:

type typeDefDummy struct {
    _      uintptr           // padding
    _      uint64            // padding
    _      [3]uintptr        // padding
    StrPtr *string           
}

然后只需调用typelinks,遍历切片并读取每个StrPtr作为名称。寻找那些以开头的人yourpackage。请注意,如果有两个yourpackage在不同路径中调用的包,则此方法将不会明确工作。

我可以以某种方式挂接到反射包中以实例化这些名称的新实例吗?

是的,假设d是type的值*typeDefDummy(请注意星号,非常重要):

t := reflect.TypeOf(*(*interface{})(unsafe.Pointer(&d)))

现在t一个reflect.Type可以实例化reflect.Values的值。

编辑:我测试并成功执行了此代码,并已将其作为要点上传

调整软件包名称,并根据需要添加路径。

自从我最初发布此答案以来,发生了很多变化。这是对如何在2019年使用Go 1.11进行相同操作的简短描述。

$GOPATH/src/tl/tl.go

package tl

import (
    "unsafe"
)

func Typelinks() (sections []unsafe.Pointer, offset [][]int32) {
    return typelinks()
}

func typelinks() (sections []unsafe.Pointer, offset [][]int32)

func Add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
    return add(p, x, whySafe)
}

func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer

$GOPATH/src/tl/tl.s

TEXT tl·typelinks(SB), $0-0
    JMP reflect·typelinks(SB)

TEXT tl·add(SB), $0-0
    JMP reflect·add(SB)

main.go

package main

import (
    "fmt"
    "reflect"
    "tl"
    "unsafe"
)

func main() {
    sections, offsets := tl.Typelinks()
    for i, base := range sections {
        for _, offset := range offsets[i] {
            typeAddr := tl.Add(base, uintptr(offset), "")
            typ := reflect.TypeOf(*(*interface{})(unsafe.Pointer(&typeAddr)))
            fmt.Println(typ)
        }
    }
}
其他 2022/1/1 18:15:16 有507人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶