繁体   English   中英

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

[英]Getting list of exported functions from a package in golang

假设我有一些 package

// ./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'")
}

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

注意:这是全部编译的,因此没有运行时限制

如果用 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/非常相似的东西“完成”了这一点,但要求每个额外的“插件”添加它的将 function 导出到 package 全局 map。 虽然这“有效”,但这感觉很hacky(好像整个程序不是......大声笑;)并且如果我可以在不需要插件编写者的任何额外工作的情况下完成它,我会更喜欢。 基本上我想让它尽可能地“放下就走”。

最简单的方法是使用模板库来解析代码,并在适当的地方插入新的程序包名称。

操场

您可以通过在调用用户包的所有决赛中加载所有总决赛,然后将生成的文件输出到执行目录来使用此功能。

正如您可能已经猜到的那样,在 Go 中很难实现,如果不是不可能的话,因为 Go 是一种编译语言。

exported functions遍历 package 只能得到函数列表。 一个示例是: Playground 这是一种 AST(抽象语法树)方法,这意味着动态调用函数是不可能的,或者需要太多的变通方法。 将 function 名称字符串解析为 function 类型在这里不起作用。

或者,您可以通过将导出的函数绑定到某种类型来使用 try methods

type Task struct {}
func (Task) Process0()
func (Task) Process1(v int)
func (Task) Process2(v float64)
func (Task) Process3(v1 bool, v2 string)

这完全改变了我们的操作方式,因为这 4 个方法现在与类型Task相关联,我们可以传递Task的空实例来调用其上定义的方法。 这可能看起来只是另一种解决方法,但在 Go 等语言中非常常见。 Playground中的一个示例,它实际上按预期工作。


在这两个示例中,我在 Playground 中使用了多个文件。 如果您不熟悉此结构,只需在本地创建工作区,如下所示,然后从 Playground 复制每个文件名下的代码:

<Your project>
├── go.mod
├── main.go
└── task
    └── task.go

参考:

  1. 如何在 Golang 中动态调用结构的所有方法? [复制]
  2. 如何检查 function arguments 和类型 [重复]
  3. 如何在golang中列出package的公共方法[重复]
  4. 抽象语法树 - Wiki
  5. Go 中的函数与方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM