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

据我所知(请参阅此处和此处)在反射包中没有类型发现机制,它期望您已经拥有要检查的类型或值的实例。


有没有其他方法可以发现正在运行的 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()对于嵌入预期库类型的类型,库代码需要以某种方式扫描正在运行的命名空间。


幕布斯7119047
浏览 183回答 3
3回答

www说

在 Go 1.5 中,您可以使用新的包类型和导入器来检查二进制包和源包。例如:package mainimport (    "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来编译源代码。

catspeake

按照您的指示,它今天仍然可以在 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)}然后现在都工作了。:)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go