为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
幕布斯7119047 2021-11-01 16:16:06
据我所知(请参阅此处和此处)在反射包中没有类型发现机制,它期望您已经拥有要检查的类型或值的实例。有没有其他方法可以发现正在运行的 go 包中的所有导出类型(尤其是结构)?这是我希望我拥有的(但它不存在):import "time"import "fmt"func main() {    var types []reflect.Type    types = reflect.DiscoverTypes(time)    fmt.Println(types)}最终目标是能够发现满足特定条件的包的所有结构,然后能够实例化这些结构的新实例。顺便说一句,识别类型的注册函数对于我的用例来说不是有效的方法。无论您认为这是一个好主意与否,这就是我想要此功能的原因(因为我知道您会问):我编写了一个代码生成实用程序,它加载 go 源文件并构建一个 AST 来扫描嵌入指定类型的类型。该实用程序的输出是一组基于发现的类型的 go test 函数。我调用此实用程序go generate来创建测试函数,然后运行go test以执行生成的测试函数。每次测试更改(或添加新类型)时,我都必须在重新运行之前重新运行 go generate go test。这就是注册功能不是有效选项的原因。我想避免这go generate一步,但这需要我的实用程序成为由正在运行的包导入的库。init()对于嵌入预期库类型的类型,库代码需要以某种方式扫描正在运行的命名空间。
查看完整描述

3 回答

?
www说

TA贡献1775条经验 获得超8个赞

在 Go 1.5 中,您可以使用新的包类型和导入器来检查二进制包和源包。例如:


package main


import (

    "fmt"

    "go/importer"

)


func main() {

    pkg, err := importer.Default().Import("time")

    if err != nil {

        fmt.Printf("error: %s\n", err.Error())

        return

    }

    for _, declName := range pkg.Scope().Names() {

        fmt.Println(declName)

    }

}

您可以使用go/build包来提取所有已安装的包。或者您可以配置Lookup导入器以检查环境之外的二进制文件。


在 1.5 之前,唯一没有黑客的方法是使用包ast来编译源代码。


查看完整回答
反对 回复 2021-11-01
?
catspeake

TA贡献1111条经验 获得超0个赞

按照您的指示,它今天仍然可以在 1.13.6 上运行。


按照你的方式 tl.s 将是:


TEXT ·typelinks(SB), $0-0

    JMP reflect·typelinks(SB)

是的,没有包名,也没有“添加”功能。


然后按照@icio的方式将“添加”功能更改为:


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

    return unsafe.Pointer(uintptr(p) + x)

}

然后现在都工作了。:)


查看完整回答
反对 回复 2021-11-01
  • 3 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信