从golang中的包中获取导出函数列表

Posted

技术标签:

【中文标题】从golang中的包中获取导出函数列表【英文标题】:Getting list of exported functions from a package in golang 【发布时间】:2016-10-18 05:42:19 【问题描述】:

假设我有一些包裹

// ./somepkg/someFile.go
package somepkg
import "fmt"
func AnExportedFunc(someArg string) 
    fmt.Println("Hello world!")
    fmt.Println(someArg)
)

然后我从我的主 go 文件中导入它

// ./main.go
package main
import (
    "./somepkg" // Let's just pretend I have the full path written out
    "fmt"
)

func main() 
    fmt.Println("I want to get a list of exported funcs from package 'somefolder'")

有没有办法从包“somepkg”访问导出的函数,然后调用它们?参数编号/类型在 somepkg 中的所有函数中都是一致的。我已经查看了反射包,但我不确定是否可以在不知道包名称以外的任何信息的情况下获取列表并调用函数。但是,我可能会从 godocs 中遗漏一些东西,所以任何建议都值得赞赏。我想要做的基本上是有一个系统,人们可以将 .go 文件作为一种“插件”放入其中。这些“插件”将有一个单独的导出函数,主程序本身将使用一致数量和类型的参数调用该函数。对该代码库的访问受到限制,因此贡献者的任意代码执行不存在安全问题。

注意:这都是编译的,所以没有运行时限制

如果用 python 编写,我想要做的是这样的事情

# test.py
def abc():
    print "I'm abc"

def cba():
    print "I'm cba"

# foo.py
import test
flist = filter(lambda fname: fname[0] != "_", dir(test))

# Let's forget for a moment how eval() is terrible
for fname in flist:
    eval("test."+fname+"()")

运行 foo.py 返回

I'm abc
I'm cba

这在 golang 中可行吗?

编辑:

我应该注意,我已经用与http://mikespook.com/2012/07/function-call-by-name-in-golang/ 非常相似的东西“完成”了这一点,但要求每个额外的“插件”将其导出的函数添加到包全局映射中。虽然这“有效”,但这感觉很hacky(好像整个程序不是......大声笑;)并且如果我可以在不需要插件编写者的任何额外工作的情况下完成它,我会更喜欢。基本上我想让它尽可能地“放下就走”。

【问题讨论】:

您无法在运行时获取导出的符号,因为这些符号仅在编译时可用。如果未使用该功能,则在链接期间将其删除。 (在当前的 gc 实现中) 我在运行时不需要它们,因为我会将“插件”编译到主程序本身中。我意识到称它们为“插件”很奇怪,因此使用引号。我主要一直在查看 ast、token、parser 和 reflect 包,我觉得有可能做我想做的事,但不太确定如何做。 如果你想在编译时做一些事情,反射包帮不了你。编译前需要解析源码并生成每个插件所需的代码。 【参考方案1】:

最简单的方法是使用template 库来解析您的代码并在适当的地方插入新的包名称。

Playground

你可以通过加载调用用户包的所有finals,然后将生成的文件输出到执行目录来使用它。

【讨论】:

以上是关于从golang中的包中获取导出函数列表的主要内容,如果未能解决你的问题,请参考以下文章

从导出的函数JS中的函数获取值

从零开始学Go之基本:包函数声明与格式化输出

包——基本概念,自定义包,创建包,导出包中的标志符

Golang中的init函数

如何获取PE到导出表中的函数地址

如何在“R”中的foreach循环中导出多个函数或包